覆盖 ActiveRecord 属性方法
Posted
技术标签:
【中文标题】覆盖 ActiveRecord 属性方法【英文标题】:Override ActiveRecord attribute methods 【发布时间】:2010-09-27 06:53:56 【问题描述】:我所说的一个例子:
class Person < ActiveRecord::Base
def name=(name)
super(name.capitalize)
end
def name
super().downcase # not sure why you'd do this; this is just an example
end
end
这似乎可行,但我刚刚阅读了ActiveRecord::Base docs 中关于覆盖属性方法的部分,它建议使用read_attribute
和write_attribute
方法。我认为我在上面的示例中所做的事情一定有问题;否则,他们为什么会祝福这些方法是覆盖属性方法的“正确方法”?他们还强迫一个更丑陋的成语,所以一定有充分的理由......
我真正的问题:这个例子有什么问题吗?
【问题讨论】:
【参考方案1】:http://errtheblog.com/posts/18-accessor-missing 提供有关此主题的一些重要信息。
总而言之,ActiveRecord 确实正确处理了对 ActiveRecord 属性访问器的超级调用。
【讨论】:
【参考方案2】:我有一个 Rails 插件,它可以像你期望的那样让属性覆盖与 super 一起工作。你可以在github找到它。
安装:
./script/plugin install git://github.com/chriseppstein/has_overrides.git
使用方法:
class Post < ActiveRecord::Base
has_overrides
module Overrides
# put your getter and setter overrides in this module.
def title=(t)
super(t.titleize)
end
end
end
一旦你完成了这些事情就可以工作了:
$ ./script/console
Loading development environment (Rails 2.3.2)
>> post = Post.new(:title => "a simple title")
=> #<Post id: nil, title: "A Simple Title", body: nil, created_at: nil, updated_at: nil>
>> post.title = "another simple title"
=> "another simple title"
>> post.title
=> "Another Simple Title"
>> post.update_attributes(:title => "updated title")
=> true
>> post.title
=> "Updated Title"
>> post.update_attribute(:title, "singly updated title")
=> true
>> post.title
=> "Singly Updated Title"
【讨论】:
【参考方案3】:作为 Aaron Longwell 回答的扩展,您还可以使用“哈希表示法”来访问具有覆盖访问器和修改器的属性:
def name=(name)
self[:name] = name.capitalize
end
def name
self[:name].downcase
end
【讨论】:
哈希表示法可能有效,但self.attribute
在 3.2.16 上破坏了堆栈。
这样的好处是支持||=
进行默认:def name; self[:name] ||= 'anon'; end
对我来说,这种哈希表示法有效。但我不知道它起作用的原因。谁能解释一下?【参考方案4】:
与 Gareth 的 cmets 相呼应...您的代码将无法按所写的那样工作。应该这样改写:
def name=(name)
write_attribute(:name, name.capitalize)
end
def name
read_attribute(:name).downcase # No test for nil?
end
【讨论】:
正是我需要的。谢谢亚伦。 这不再是真的。要么超级,要么现在有效。不过,我还没有测试过哈希表示法。 在rails 3中,Aaron在此处指定的阅读器方法有效,但原始海报指定的作者(将名称提供给super)工作正常,恕我直言,比手动将属性写入Aaron更干净建议。 我已经测试了下面 mipadi 给出的哈希方法,它就像一个魅力(Rails v 3.2.6) 这已在 Rails 6.1 中删除:github.com/rails/rails/commit/…以上是关于覆盖 ActiveRecord 属性方法的主要内容,如果未能解决你的问题,请参考以下文章
如何在具有名为“属性”的列的数据库上使用 ActiveRecord? (危险属性错误)