1

ユースケース

私は3つのモデルを持っています:

  • aMessage
  • aConversation
  • aMessageRecipient

関係は次のように定義されます。

  • A message has_and_belongs_to_many conversations(逆)
  • message has_many message_recipients
  • A MessageRecipient belongs_toamessageおよび a recipient(ここでは定義されていません)

動作するケース

方法

@recipient.inbox_conversations.first.messages

次の SQL クエリを作成します。

SELECT *
FROM `messages`
INNER JOIN `conversations_messages`
  ON `messages`.id = `conversations_messages`.message_id
WHERE (`conversations_messages`.conversation_id = 2061 ) 

結果は予想されるメッセージです:

[#<Message id: 7045, ..>]

問題

次のメソッド (前のメソッドとまったく同じで、名前付きスコープが追加されています)

@recipient.inbox_conversations.first.messages.received_by(@recipient)

次の SQL クエリを作成します。

SELECT * FROM `messages`
INNER JOIN `message_recipients`
  ON `message_recipients`.message_id = `messages`.id
INNER JOIN `conversations_messages`
  ON `conversations_messages`.message_id = `messages`.id
WHERE (`conversations_messages`.conversation_id = 2060 )
  AND (`message_recipients`.recipient_id = 32363)

存在しない ActiveRecord 要素を返します

[#<Message id: 9025, ..>]

Message.find_by_id(9025)この行の直後に実行しようとしましたが、これは を返しますnil

追加のコードが必要ですか?

class Message

named_scope :received_by, lambda { |recipient| {
  :conditions => [ "`#{MessageRecipient.table_name}`.recipient_id = ?", recipient.id ],
  :joins => "INNER JOIN `#{MessageRecipient.table_name}`
   ON `#{MessageRecipient.table_name}`.message_id = `#{Message.table_name}`.id"
} }

.

class Receiver

def inbox_conversations
  inbox_messages = Message.received_by(self).find(:all, :include => :conversations)
  return inbox_messages.map(&:conversations).flatten.uniq
end

これを読んでくれてありがとう!

4

1 に答える 1

2

問題は、結果セット内の 2 つ以上の列が同じ名前の場合、Rails 2 が特にスマートではないことです。Rails は列名のみを参照するため、これらは互いに上書きされます。あなたの場合、結合されたテーブルの1つからのIDは、メッセージテーブルからのIDを隠しています。

選択オプションをスコープに追加して、メッセージ テーブルから列のみを取得するか ( :select => 'messages.*')、結合されたテーブルから列が必要な場合は必要なものだけを選択し、競合する列名にエイリアスを設定する必要があります。

于 2013-07-18T18:00:36.160 に答える