覆盖ActiveRecord属性方法

时间:2008-12-17 05:31:46

标签: ruby-on-rails oop 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::Base docs中覆盖属性方法的部分,并建议使用read_attributewrite_attribute方法。我认为在上面的例子中我所做的事情肯定有问题;否则,为什么他们会将这些方法作为覆盖属性方法的“正确方法”?他们也强迫一个更丑陋的习语,所以必须有一个很好的理由......

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

4 个答案:

答案 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"