2012-08-25 123 views
2

我需要在我发送的消息和从某人收到的消息之间进行联合。两个ActiveRecord之间的联盟::关系

这是我在控制器中尝试做的第一件事,但消息没有排序。我想我需要做一个真正的联盟?

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 

回答

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]) 

而且还有使用在操作(这将如果用户只工作的另一个(在我看来,略多ellegant)解决方案不能发送消息给自己):

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

在这两种解决方案中,您可以使用通常的排序或分页。

+0

谢谢。我用了最后一个 – Medmax

1

如果您不必使用活动记录,则可以这样做。
这意味着,你不需要额外的条件。

@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)