重写 ActiveRecord 属性方法

举个例子:

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: : 基本文档中重写属性方法的部分,它建议使用 read_attributewrite_attribute方法。我认为我在上面的例子中所做的一定有什么问题; 否则,为什么他们会祝福这些方法作为覆盖属性方法的“正确方法”?他们还强加了一个更丑陋的成语,所以一定有很好的理由..。

我真正的问题是: 这个例子有什么问题吗?

70697 次浏览

重复 Gareth 的注释... 你的代码不会按照编写的方式工作,应该这样重写:

def name=(name)
write_attribute(:name, name.capitalize)
end


def name
read_attribute(:name).downcase  # No test for nil?
end

作为 Aaron Longwell 答案的扩展,你也可以使用“ hash 符号”来访问那些覆盖了访问器和变异器的属性:

def name=(name)
self[:name] = name.capitalize
end


def name
self[:name].downcase
end

我有一个 Rails 插件,使属性覆盖工作与超级你会期望。你可以在 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"

http://errtheblog.com/posts/18-accessor-missing上有一些关于这个主题的重要信息。

简而言之,ActiveRecord 能够正确地处理对 ActiveRecord 属性访问器的超级调用。