【问题标题】:How to add methods to has_many relationship on runtime如何在运行时向 has_many 关系添加方法
【发布时间】:2023-04-09 22:05:01
【问题描述】:

我正在尝试向 has_many 关系添加迟到的方法,我不想在构建时这样做(:has_many panties do ... end),也不想在一定范围内这样做(我希望它在每个 has_many 或集合关联中都能工作)。我已经试过了:

  1. 在 ActiveRecord::Associations::CollectionAssociation 类中包含方法
  2. 在 ActiveRecord::Associations::CollectionProxy 类中包含方法

似乎没有任何效果。我只能跟踪未定义的方法将被传递给类,这不是我想要的。

我想要的结果是这样的:

class Man < ActiveRecord::Base
  has_many :balls
end

class Woman < ActiveRecord::Base
  has_many :breasts
end

# magic to insert methods

Man.new.balls.say_hi #=> "hi jerry"
Woman.new.breasts.say_hi #=> "hi jerry"

如此简单,却又如此困难。 AR 中的这种方法代理使得调试变得非常困难。

编辑:

我的目的不是插入更多业务逻辑,而是为集合添加组合,以便我提取有关集合的信息并在其他地方使用它。我重复一遍,这些信息与业务逻辑无关,而是与一些“隐藏”在集合关联中的活动记录信息有关,例如知道哪个类是子类、父类中的关联名称等。

然后可以通过#composite_object 之类的收集方法获得此复合对象,该方法将为我提供此信息。但是我不知道如何在不重新定义关联的情况下插入此方法。

【问题讨论】:

  • 这个问题没有多大意义,如果你想对一组子项执行一个方法,那么正确的位置是在父项中。您的示例无助于解释您要解决的方案。还有就是有点粗俗。
  • 我不想完全针对孩子,而是针对收藏本身。我想使用组合来扩展组合并从中提取某些信息以用于后续模块。

标签: ruby-on-rails activerecord


【解决方案1】:

你考虑过 ActiveRecord::QueryMethods#extending 方法吗? http://apidock.com/rails/ActiveRecord/QueryMethods/extending

module Belatedly
  def say_hi
    "hi jerry"
  end
end

children = Child.all.extending Belatedly
children.say_hi

class Parent < ActiveRecord::Base
  has_many :children, -> { extending Belatedly }
end

Parent.first.children.say_hi

【讨论】:

    【解决方案2】:

    您需要通过一个开放模块为has_many 定义一个环绕别名,该别名驻留在ActiveRecord::Associations::ClassMethods 中。

    别名周围会简单地调用旧的has_many 方法,然后使用define_method 添加say_hi

    【讨论】:

    • 我的目的不是给活动记录添加别名,而是在关联的集合中干净地插入方法。这适用于 gem,如果所有 gem 开始为自己的目的使用别名 has_many,最终会爆炸。$
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-20
    • 2013-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多