My application is on Rails 2.
I have 2 models, joined by a has_and_belongs_to_many relation : Message and Conversation.
So I have 3 tables, messages, conversations and conversations_messages.
Is it possible to load in one unique query both objects Message and Conversation, without using the :include option ? The :include option is impossible because my query depends of some external params.
Example :
I can do a query from Message to have a couple of (Message,Conversation) per line
messages = Message.find(:all,
:select => "messages.*, conversations.*",
:conditions => some_conditions_depending_of_external_variables
:group => "messages.id"
)
The resulting table looks like :
`messages`.id | `messages`.field | `conversations`.id | `conversations`.field
--------------+------------------+--------------------+------------------
1 | ... | 10 | ...
--------------+------------------+--------------------+------------------
2 | ... | 15 | ...
--------------+------------------+--------------------+------------------
3 | ... | 10 | ...
--------------+------------------+--------------------+------------------
4 | ... | 20 | ...
After this query, my variable messages contains a set of AR Messages elements, but the conversations fields are not loaded as an AR Conversation.
I want to be able to call a message.linked_conversation to have the conversation of the same line, as an AR object.
Is there any method to do this without re-loading the objects ?
It is possible.
You have to manually do something that :include does internally. It means integrating with AR internal API, which is not something you normally wish to do - it can break at any time when you're upgrading Rails.
This means you should:
Altough I suggest splitting into two queries, so that the you load Conversation objects through a second query - based on the conversation ids you get in the first query. It is better for performance in most cases. After that you just need attach loaded objects into association of Message objects.
To give you a rough example of the logic:
# complex query to load messages and conversation ids
messages = Message.find(...)
# parse the loaded conversation ids out of resulting Message objects
con_ids = messages.map {...}
# load conversation objects through 2nd query
conversations = Conversations.find(con_ids)
# group conversations by message id
con_by_message = conversations.group_by(&:message_id)
# attach conversations into associations of Message objects
messages.each {|m|
m.conversations.target = con_by_message[m.id] || []
}
This is something that worked for has_many associations in Rails. I can't tell you if setting association.target is enough for habtm associations - you should digg up that in the source...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With