2

我的应用程序在 Rails 2 上。

我有 2 个模型,通过has_and_belongs_to_many关系 :MessageConversation. 所以我有 3 个表messagesconversationsconversations_messages

是否可以在一个唯一查询中同时加载对象MessageConversation,而不使用该:include选项?该:include选项是不可能的,因为我的查询取决于一些外部参数。

例子 :

我可以从 Message 查询每行有几个 ( Message, )Conversation

messages = Message.find(:all,
  :select => "messages.*, conversations.*",
  :conditions => some_conditions_depending_of_external_variables
  :group => "messages.id"
)

结果表如下所示:

`messages`.id | `messages`.field | `conversations`.id | `conversations`.field
--------------+------------------+--------------------+------------------
1             | ...              | 10                 | ...
--------------+------------------+--------------------+------------------
2             | ...              | 15                 | ...
--------------+------------------+--------------------+------------------
3             | ...              | 10                 | ...
--------------+------------------+--------------------+------------------
4             | ...              | 20                 | ...

在此查询之后,我的变量messages包含一组 AR 消息元素,但对话字段未作为 AR 对话加载。

我希望能够调用 message.linked_conversation 来进行同一行的对话,作为 AR 对象。

有什么方法可以在不重新加载对象的情况下做到这一点?

4

1 回答 1

1

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:

  1. instantiate Conversation objects manually from query result
  2. attach loaded Conversation objects to the association in Message objects

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...

于 2013-07-29T09:20:41.410 回答