渴望加载的关系很多的最新项

问题描述

| 我有两个模型:
Conversation
Message
。一条消息属于对话,一条对话有许多条消息:
# conversation.rb
class Conversation < ActiveRecord::Base
  has_many :messages
end

# message.rb
class Message < ActiveRecord::Base
  belongs_to :conversation
end
我有一个界面,该界面将列出所有对话,但我也想通过渴望加载包括与对话关联的“最新”消息。 我是否需要在会话和将跟踪最新消息的消息之间创建新的has_one或belongs_to关系?还是有一种方法可以通过使用联接/包含的作用域来做到这一点? 编辑:问题是我不希望在此循环的每次迭代中执行SQL查询
# controller
@conversations = Conversation.all

# view
@conversations.each do |conversation|
  most_recent_message = conversation.messages.last
  # ...
end
编辑2:我也尝试执行以下操作,但未成功。目的是在会话表中添加一个“ 4”列,以允许其引用最后添加的消息。
# migration
add_column :conversations,:last_message_id,:integer

# conversation.rb
belongs_to :last_message,:class_name => \'Message\'

# message.rb
after_create :set_last_message_on_conversation

def set_last_message_on_conversation
  self.conversation.last_message = self
  self.conversation.save!
end
但是,这会导致sql错误,因为在创建会话时last_message_id为null。 (我希望这一切都将在事务中发生,并且last_message_id将在事务完成之前进行更新,但是我认为这是MysqL / MyISAM问题,其中不使用事务。)   ActiveRecord :: StatementInvalid:MysqL :: Error:列\'last_message_id \'不能为空:INSERT INTO`conversations`(`last_message_id`,`updated_at`,`created_at`)值(NULL,\'2011-05-31 16 :57:11 \',\'2011-05-31 16:57:11 \')     

解决方法

        您可以使用其他关联:
# conversation.rb
class Conversation < ActiveRecord::Base
  has_many :messages
  has_one :last_message,:class_name => \"Message\",:order => \"created_at DESC\"
end

# controller
@conversations = Conversation.includes(:last_message)

# view
@conversations.each do |conversation|
  most_recent_message = conversation.last_messages
  # ...
end
警告“ that7”和“ѭ8”,并认为它们是独立的协会。如果使用
conversation.messages
,将从数据库中加载消息。而且,如果更改属性
last_message
,则在重新加载之前不会影响
messages.last
。 编辑:实际上,根据日志,ActiveRecord仍会加载所有对话的消息。可能是因为它不能\“ LIMIT 1 \”像它不渴望加载时一样。 因此,就SQL请求而言,此解决方案似乎等同于仅使用
Conversation.includes(:messages)
。但是也许在使用
has_one
关联时,Rails不会处理额外的结果。     ,        从什么意义上说,延迟加载是什么意思?只是在加载对话时未加载最新消息?尝试这个:
class Conversation < ActiveRecord::Base
  has_many :messages,:order => \"created_at\"
end
那你可以打电话
@conversation.messages.last
正在执行SQL
SELECT \"messages\".* FROM \"messages\" WHERE (\"messages\".conversation_id = 129) ORDER BY created_at DESC LIMIT 1
在您实际要求最后一条消息时。 重要说明:如果在执行动作之前在此之前调用@ conversation.messages,则它可能已经加载了所有消息,因此在调用@ conversation.messages.last时可能不会再次访问数据库。因此,如果在对@ conversation.messages和@ conversation.messages.last的调用之间添加了一条消息,您将不会得到真正的最后一条消息。但我想这可能还好吗?