【问题标题】:How do you override the getter method for a Rails has_one association?如何覆盖 Rails has_one 关联的 getter 方法?
【发布时间】:2012-10-14 20:01:48
【问题描述】:

我想覆盖/扩展 Rails has_one 关联方法,以便它始终返回关联类的实例。 (如果数据库中不存在,我想创建一个新的并将其分配给父实例。)

理想情况下,我想通过built-in Rails association extension mechanism 来完成此操作。但是,我不知道“getter”方法的名称,所以我不知道要覆盖什么。

如何覆盖关联 getter,以便在它为 nil 时实例化一个新对象?

【问题讨论】:

  • 覆盖 has_one 关联宏可能会导致流泪。我选择 1) 回填缺失数据的迁移和 2) 在父资源上具有 after_create 侦听器的观察者。
  • @TomL:我会记住这一点,但在这种特殊情况下,我希望实际实例(不仅仅是数据)在引用时立即可用(并且之前不存在) .
  • 你可以在父控制器中处理它。在new 操作中执行@parent = Parent.new(:child => Child.new) 之类的操作。在edit 操作中执行@parent = Parent.find(params[:id]) 然后@parent.child = Child.new unless @parent.child.present?。类似的东西。

标签: ruby-on-rails ruby-on-rails-3 associations has-one


【解决方案1】:

您可以为原始方法设置别名,然后定义一个具有相同名称的新方法。

例如:

class MyModel < ActiveRecord::Base
  has_one :associated_model

  alias :old_associated_model :associated_model

  def associated_model
    old_associated_model || AssociatedModel.new(my_model_id: id)
  end

end

我不知道这是否是处理这种情况的规范方法,但它应该可以工作。

【讨论】:

  • 这肯定行得通。我希望使用记录在案的方式来扩展关联,但这是我的后备计划。
【解决方案2】:

从 Rails 3 开始,alias_method 不是覆盖关联方法的首选方式。引用自docs

覆盖生成的方法

关联方法是在一个包含在模型类中的模块中生成的,它允许您轻松地用自己的方法覆盖并使用 super 调用原始生成的方法。例如:

class Car < ActiveRecord::Base
  belongs_to :owner
  belongs_to :old_owner
  def owner=(new_owner)
    self.old_owner = self.owner
    super
  end
end

如果您的模型类是 Project,则该模块名为 Project::GeneratedFeatureMethods。 GeneratedFeatureMethods 模块包含在模型类中(匿名)生成的属性方法模块之后,这意味着关联将覆盖具有相同名称的属性的方法。

【讨论】:

  • 哈哈,厉害!偶然发现朋友的答案就像是某种命运的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-22
  • 1970-01-01
  • 2015-07-30
  • 1970-01-01
  • 2011-01-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多