我正在努力创造一个非常复杂的急切负载;我想修改第二个声明,而不是第一个声明。我需要在第二个语句上创建一个连接,其中包含另一个表中的列。
我尝试的所有内容都会修改第一个语句并保留第二个语句。如果有另一种方法可以在没有N + 1查询的情况下完成相同的任务,我就会打开。
此:
Conversation.joins(:phones)
.where('phones.id' => 2)
.order('last_message_at DESC')
.includes(:messages)
生成:
SELECT "conversations".* FROM "conversations"
INNER JOIN "conversations_phones"
ON "conversations_phones"."conversation_id" = "conversations"."id"
INNER JOIN "phones"
ON "phones"."id" = "conversations_phones"."phone_id"
WHERE "phones"."id" = 2 ORDER BY last_message_at DESC
SELECT "messages".* FROM "messages"
WHERE "messages"."conversation_id" IN (10, 11) ORDER BY created_at ASC
有道理,但不是我想去的地方。
我可以用这样的东西写下所需的第二个陈述:
Message.joins(:message_tags)
.select('messages.*, message_tags.status as read')
.group('messages.id, message_tags.status')
.order('messages.id')
.where(:message_tags => { :user_id => current_user.id })
.where(:messages => { :conversation_id => [10, 11] })
哪个正确生成:
SELECT messages.*, message_tags.status as read FROM "messages"
INNER JOIN "message_tags" ON "message_tags"."message_id" = "messages"."id"
WHERE "message_tags"."user_id" = 2 AND "messages"."conversation_id" IN (10, 11)
GROUP BY messages.id, message_tags.status
ORDER BY messages.id
基本上,我希望选择更复杂的消息来替换更简单的消息,这样我就可以在不创建新查询的情况下调用@ conversations.first.messages.first.read。
答案 0 :(得分:1)
听起来你需要为协会添加一些条件:
has_many :messages, -> { select('messages.*, message_tags.status as read')) }
然后像:
Conversation.joins(:phones)
.where('phones.id' => 2)
.order('last_message_at DESC')
.includes(:messages => :message_tags)
.where(:message_tags => { :user_id => current_user.id })