2

送信したメッセージと誰かから受信したメッセージを結合する必要があります。

これがコントローラーで最初に実行しようとしたことですが、メッセージは順序付けられていません。私は本当の連合をする必要があると思いますか?

def listmessages
   @messages1 = current_user.messages.where(:sender_id => params[:sender_id])
   @messages2 = current_user.sent_messages.where(:recipient_id => params[:sender_id])
   @messages = @messages1 + @messages2
end

これが私のユーザーモデルです:

class User < ActiveRecord::Base
   before_create :distribute_points

   devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable, :confirmable

   has_many :sent_messages, foreign_key: "sender_id", class_name:"Message",
       order: "created_at DESC"

   has_many :messages, foreign_key: "recipient_id", order: "created_at DESC"
end
4

2 に答える 2

5

結果を使用する場合+、メッセージは最初にメモリ内の配列に読み込まれ、次にこれらの配列が連結されます。したがって、順序を保存するには、もう一度並べ替える必要があります。醜い...そして歴史が大きくなると非常に遅くなります。

実際のUNIONを使用することもできますが、多くの生のSQL(からMessage.find_by_sql("your union query"))が必要であり、非常に醜く、保守が困難です。

あなたの場合、代わりにUNIONを使用する方が良いかもしれません:

@messages = Message.where('(sender_id = ? AND recipient_id = ?) OR (recipient_id = ? AND sender_id = ?)', current_user.id, params[:sender_id], current_user.id, params[:sender_id])

そして、IN操作を使用する別の(そして私の意見では、もう少しエレガントな)解決策があります(これは、ユーザーが自分自身にメッセージを送信できない場合にのみ機能します):

@messages = Message.where(:sender_id => [current_user.id, params[:sender_id]], :recipient_id => [current_user.id, params[:sender_id])

どちらのソリューションでも、通常どおり注文またはページネーションを使用できます。

于 2012-08-25T16:24:40.557 に答える
1

アクティブレコードとして使用する必要がない場合は、このようにすることができます。
つまり、where条件を追加する必要はありません。

@message = @message1.to_set + @message2.to_set

また

@message = @message1.to_a + @message2.to_a

しかし、本当に結果をアクティブレコードとして使用する必要がある場合は、このようなパフォーマンスを怖がらせる可能性があります。

messages_set = @message1.map { |m| m.id }.to_set + @message2.map { |m| m.id }.to_set
@message = Message.where(:id => messages_set.to_a)
于 2013-05-21T08:58:43.493 に答える