在 Ruby on Rails 中重写 setter 方法的正确方法是什么? [英] What is the right way to override a setter method in Ruby on Rails?

查看:36
本文介绍了在 Ruby on Rails 中重写 setter 方法的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Ruby on Rails 3.2.2,我想知道以下是否是覆盖我的类属性的 setter 方法的正确"/正确"/确定"方法.

I am using Ruby on Rails 3.2.2 and I would like to know if the following is a "proper"/"correct"/"sure" way to override a setter method for a my class attribute.

attr_accessible :attribute_name

def attribute_name=(value)
  ... # Some custom operation.

  self[:attribute_name] = value
end

上面的代码似乎按预期工作.但是,我想知道,通过使用上面的代码,将来我是否会遇到问题,或者至少,Ruby on Rails应该期待"/可能发生"什么问题.如果这不是重写 setter 方法的正确方法,那么正确的方法是什么?

The above code seems to work as expected. However, I would like to know if, by using the above code, in future I will have problems or, at least, what problems "should I expect"/"could happen" with Ruby on Rails. If that isn't the right way to override a setter method, what is the right way?

注意:如果我使用代码

attr_accessible :attribute_name

def attribute_name=(value)
  ... # Some custom operation.

  self.attribute_name = value
end

我收到以下错误:

SystemStackError (stack level too deep):
  actionpack (3.2.2) lib/action_dispatch/middleware/reloader.rb:70

推荐答案

============================================================================更新:2017 年 7 月 19 日

现在 Rails文档 还建议像这样使用 super:

Now the Rails documentation is also suggesting to use super like this:

class Model < ActiveRecord::Base

  def attribute_name=(value)
    # custom actions
    ###
    super(value)
  end

end

============================================================================

原答案

如果您想在通过模型访问时覆盖表列的 setter 方法,这就是这样做的方法.

If you want to override the setter methods for columns of a table while accessing through models, this is the way to do it.

class Model < ActiveRecord::Base
  attr_accessible :attribute_name

  def attribute_name=(value)
    # custom actions
    ###
    write_attribute(:attribute_name, value)
    # this is same as self[:attribute_name] = value
  end

end

参见 覆盖默认值Rails 文档中的访问器.

因此,您的第一种方法是在 Models of Ruby on Rails 中覆盖列设置器的正确方法.Rails 已经提供了这些访问器来访问表的列作为模型的属性.这就是我们所说的 ActiveRecord ORM 映射.

So, your first method is the correct way to override column setters in Models of Ruby on Rails. These accessors are already provided by Rails to access the columns of the table as attributes of the model. This is what we call ActiveRecord ORM mapping.

还要记住,模型顶部的 attr_accessible 与访问器无关.它具有完全不同的功能(请参阅 这个问题)

Also keep in mind that the attr_accessible at the top of the model has nothing to do with accessors. It has a completely different functionlity (see this question)

但是在纯 Ruby 中,如果您为类定义了访问器并想覆盖 setter,则必须像这样使用实例变量:

But in pure Ruby, if you have defined accessors for a class and want to override the setter, you have to make use of instance variable like this:

class Person
  attr_accessor :name
end

class NewPerson < Person
  def name=(value)
    # do something
    @name = value
  end
end

一旦您知道 attr_accessor 的作用,就会更容易理解.代码 attr_accessor :name 等价于这两个方法(getter 和 setter)

This will be easier to understand once you know what attr_accessor does. The code attr_accessor :name is equivalent to these two methods (getter and setter)

def name # getter
  @name
end

def name=(value) #  setter
  @name = value
end

您的第二种方法也失败了,因为当您在该方法中调用相同的方法 attribute_name= 时,它会导致无限循环.

Also your second method fails because it will cause an infinite loop as you are calling the same method attribute_name= inside that method.

这篇关于在 Ruby on Rails 中重写 setter 方法的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆