覆盖ActiveRecord属性方法


150

我在说的一个例子:

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_attributeand write_attribute方法。我认为以上示例中的操作一定存在问题;否则,为什么他们会认为这些方法是覆盖属性方法的“正确方法”?他们也强迫使用更丑陋的习惯用法,因此一定有充分的理由...

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

Answers:


211

呼应Gareth的评论...您的代码将无法正常运行。应该这样重写:

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

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

正是我所需要的。谢谢亚伦。

18
这不再是事实。超级或现在可以使用。但是,我尚未测试哈希符号。
heartpunk

2
在rails 3中,由Aaron在此处指定的reader方法可以工作,但是指定原始海报(将名称输入super)的作者可以正常工作,并且IMHO比Aaron建议的手动编写属性干净。
巴特金斯2011年

1
我已经测试了由
mipadi

这不是正确的答案吗?谢谢@Aaron,也为我工作。
Sadiksha Gautam

94

作为对Aaron Longwell答案的扩展,您还可以使用“哈希符号”来访问已覆盖访问器和变异器的属性:

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

def name
  self[:name].downcase
end

哈希表示法可能会起作用,但会self.attribute在3.2.16上使堆栈失效。
jrhorn424 2014年

这具有支持||=默认设置的优点:def name; self[:name] ||= 'anon'; end
Paul Cantrell,2016年

对我而言,此哈希符号有效。但是我不知道它起作用的原因。有人可以解释吗?
radiantshaw


-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"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.