Ruby-on-rails 覆盖 ActiveRecord 属性方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/373731/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 20:51:20  来源:igfitidea点击:

Override ActiveRecord attribute methods

ruby-on-railsoopactiverecord

提问by Aaron Longwell

An example of what I'm talking about:

我正在谈论的一个例子:

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

This seems to work, but I was just read the section on overriding attribute methods in the ActiveRecord::Base docs, and it suggests using the read_attributeand write_attributemethods. I thought there must be something wrong with what I'm doing in the example above; otherwise, why would they bless these methods as the "right way" to override attribute methods? They're also forcing a much uglier idiom, so there must be a good reason...

这似乎有效,但我刚刚阅读了ActiveRecord::Base docs 中关于覆盖属性方法的部分,它建议使用read_attributewrite_attribute方法。我认为我在上面的例子中所做的一定有问题;否则,为什么他们会祝福这些方法是覆盖属性方法的“正确方法”?他们还强迫使用更丑陋的习语,所以一定有一个很好的理由......

My real question: Is there something wrong with this example?

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

回答by Aaron Longwell

Echoing Gareth's comments... your code will not work as written. It should be rewritten this way:

回应 Gareth 的评论……您的代码将无法正常工作。应该这样改写:

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

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

回答by mipadi

As an extension to Aaron Longwell's answer, you can also use a "hash notation" to access attributes that have overridden accessors and mutators:

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

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

def name
  self[:name].downcase
end

回答by jcnnghm

There is some great information available on this topic at http://errtheblog.com/posts/18-accessor-missing.

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

The long and short of it is that ActiveRecord does correctly handle super calls for ActiveRecord attribute accessors.

总而言之,ActiveRecord 确实正确处理了对 ActiveRecord 属性访问器的超级调用。

回答by chriseppstein

I have a rails plugin that makes attribute overriding work with super as you would expect. You can find it on github.

我有一个 rails 插件,它使属性覆盖与您期望的 super 一起使用。你可以在github上找到它。

To install:

安装:

./script/plugin install git://github.com/chriseppstein/has_overrides.git

To use:

使用:

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

Once you've done that things just work:

一旦你完成了这些事情就可以了:

$ ./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"