2011-04-23 73 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