has_many关联after_load类型回调

时间:2011-04-23 20:16:23

标签: ruby-on-rails ruby-on-rails-3 activerecord associations

我想记录一组个人之间的互动,每个人都建模为发送者和接收者的消息:

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'关联回调存在。还有其他我可以使用的东西,或者更好的方法来解决这种情况吗?

1 个答案:

答案 0 :(得分:1)

对于任何有兴趣的人,最后我深入研究了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