has_many 关联 after_load 类型回调

发布于 2024-11-02 22:02:25 字数 1503 浏览 2 评论 0原文

我想记录一组个体之间的交互,每个个体被建模为与发送者和接收者的消息:

class Message < ActiveRecord::Base
  belongs_to :receiver, :class_name => 'Individual', :foreign_key => 'receiver_id'
  belongs_to :sender, :class_name => 'Individual', :foreign_key => 'sender_id'
end

我想添加一个接口,通过该接口我可以记录从个体的角度发送的消息:

@bob.messages.new(:direction => 'to', :correspondent => @jane)

理想情况下,这会表现出来与 active_record has_many 关联完全相同。我决定对消息模型进行子类化,旨在创建可以以这种方式响应的东西 - 仅仅将方法添加到 Message 类似乎并不合适,因为对象需要对其“主要个体”有一些了解(在上面的情况下 @bob) 以便知道要创建哪个消息。

class Individual < AcitveRecord::Base
  has_many :received_messages, :class_name => 'Message', :foreign_key => 'receiver_id'
  has_many :sent_messages, :class_name => 'Message', :foreign_key => 'sender_id'

  has_many :messages, :class_name => 'MyMessage',
                  :finder_sql =>'SELECT * FROM messages WHERE receiver_id = #{id} OR sender_id = #{id}',
                  :after_add => :set_user

  def set_user(my_message)
    my_message.principal_user = self
  end

  class MyMessage < Message
    attr_accessor :principal_user  
    def correspondent
      @principal_user == receiver ? sender : receiver
    end

    def direction
      @principal_user == receiver ? "to" : "from"
    end
    ... other methods ...
  end
end

这几乎达到了我想要的效果。不幸的是,after_add 回调仅在将新对象添加到消息集合中时触发,而不是在每个对象首次加载到关联中时触发。

据我发现不存在“after_load”关联回调。我还可以使用其他方法,或者有更好的方法来处理这种情况吗?

I want to record interactions between a group of individuals each modelled as a message with a sender and a receiver:

class Message < ActiveRecord::Base
  belongs_to :receiver, :class_name => 'Individual', :foreign_key => 'receiver_id'
  belongs_to :sender, :class_name => 'Individual', :foreign_key => 'sender_id'
end

I would like to add an interface whereby I can record a message being sent from the point of view of an individual:

@bob.messages.new(:direction => 'to', :correspondent => @jane)

Ideally this would behave exactly like an active_record has_many association. I decided to subclass the message model, aiming to create something that could respond in this way - it didn't seem appropriate to just add the methods to the Message class, as the object needs to have some knowledge of its 'principal individual' (in the case above @bob) in order to know which Message to create.

class Individual < AcitveRecord::Base
  has_many :received_messages, :class_name => 'Message', :foreign_key => 'receiver_id'
  has_many :sent_messages, :class_name => 'Message', :foreign_key => 'sender_id'

  has_many :messages, :class_name => 'MyMessage',
                  :finder_sql =>'SELECT * FROM messages WHERE receiver_id = #{id} OR sender_id = #{id}',
                  :after_add => :set_user

  def set_user(my_message)
    my_message.principal_user = self
  end

  class MyMessage < Message
    attr_accessor :principal_user  
    def correspondent
      @principal_user == receiver ? sender : receiver
    end

    def direction
      @principal_user == receiver ? "to" : "from"
    end
    ... other methods ...
  end
end

This does almost what I want. Unfortunately the after_add callback fires only when new objects are added to the messages collection, not when each object is loaded into the association for the first time.

As far as I've found no 'after_load' association callback exists. Is there something else I can use, or a better way to approach this situation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

奢华的一滴泪 2024-11-09 22:02:25

对于任何感兴趣的人,最后我深入研究了 ActiveRecord 并得出以下结论:

 has_many :messages, :class_name => 'MyMessage',
                  :finder_sql =>'SELECT * FROM messages WHERE receiver_id = #{id} OR sender_id = #{id}',
                  :after_add => :set_user do
                    def find_target
                      messages = super
                      messages.each {|m| m.principal_user = proxy_owner}
                      messages
                    end
                  end

For anyone interested, in the end I delved into ActiveRecord and came up with the following:

 has_many :messages, :class_name => 'MyMessage',
                  :finder_sql =>'SELECT * FROM messages WHERE receiver_id = #{id} OR sender_id = #{id}',
                  :after_add => :set_user do
                    def find_target
                      messages = super
                      messages.each {|m| m.principal_user = proxy_owner}
                      messages
                    end
                  end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文