has_many association after_load type callback
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 bett开发者_JAVA技巧er way to approach this situation?
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
精彩评论