2011-04-23 47 views
2

我想记录一组个体的各模拟为具有一个发送者的消息和接收器之间的相互作用:的has_many关联after_load类型的回调

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'关联回调存在。有什么我可以使用,或更好的方法来处理这种情况?

+0

什么是你用'MyMessage'对象在做什么?它就像一个留言板,人们可以从收件箱和发件箱中删除东西吗? – 2011-04-23 22:24:25

+0

所描述的情况是我能想到的最简单的一个,它捕捉到了问题。我实际上并没有试图创建一个消息框。想一想每一次他们给对方发送一条消息,而不是看一个人群并记录下来。 'MyMessage'对象仅用于提供用于创建'Message'对象的不同接口,但是它可以识别它所属的对象之一。 – 2011-04-23 22:49:49

+0

您何时需要从接收器的角度创建一条消息?消息在发送时创建。 – 2011-04-23 22:55:03

回答

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