【问题标题】:Load several ActiveRecord models in one query在一个查询中加载多个 ActiveRecord 模型
【发布时间】:2013-07-29 08:04:21
【问题描述】:

我的应用程序在 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 对象。

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

【问题讨论】:

标签: ruby-on-rails rails-activerecord ruby-on-rails-2


【解决方案1】:

有可能。

您必须手动执行 :include 在内部执行的操作。这意味着与 AR 内部 API 集成,这不是您通常希望做的事情 - 当您升级 Rails 时,它可能随时中断。

这意味着你应该:

  1. 根据查询结果手动实例化对话对象
  2. 将加载的对话对象附加到消息对象中的关联

尽管我建议拆分为两个查询,以便您通过第二个查询加载对话对象 - 基于您在第一个查询中获得的对话 ID。在大多数情况下,它对性能更好。之后,您只需要将加载的对象附加到 Message 对象的关联中。

给你一个粗略的逻辑例子:

# 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] || []
}

这适用于 Rails 中的 has_many 关联。我不能告诉你设置 association.target 是否足以满足 habtm 关联 - 你应该在源代码中挖掘它......

【讨论】:

  • 当然,这就是我正在做的事情。但我担心 Rails 对大数据的一些处理(如 group_by)......这就是为什么我一直在寻找 ActiveRecord 的一些功能,它可以实例化一个已经存在的对象。 new 不能工作(它将是一个新记录); create 要么(将创建另一个对象)...
  • 试着看看 Rails 正在做什么......github.com/rails/rails/blob/2-3-stable/activerecord/lib/… 如果你能做一些#find_by_sql 所做的事情:connection.select_all(sanitize_sql(sql), "#{name} Load").collect ! { |记录|实例化(记录)}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-01
  • 2021-01-05
  • 1970-01-01
相关资源
最近更新 更多