我正在谈论的一个例子:
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
方法。我认为在上面的例子中我所做的事情肯定有问题;否则,为什么他们会将这些方法作为覆盖属性方法的“正确方法”?他们也强迫一个更丑陋的习语,所以必须有一个很好的理由......
我真正的问题:这个例子有问题吗?
答案 0 :(得分:208)
回应Gareth的评论......你的代码将无法按照书面形式运作。它应该以这种方式重写:
def name=(name)
write_attribute(:name, name.capitalize)
end
def name
read_attribute(:name).downcase # No test for nil?
end
答案 1 :(得分:91)
作为Aaron Longwell答案的扩展,您还可以使用“哈希表示法”来访问具有被覆盖的访问者和变更器的属性:
def name=(name)
self[:name] = name.capitalize
end
def name
self[:name].downcase
end
答案 2 :(得分:7)
在http://errtheblog.com/posts/18-accessor-missing上有关于此主题的一些很好的信息。
它的长短是ActiveRecord正确处理ActiveRecord属性访问器的超级调用。
答案 3 :(得分:-1)
我有一个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"