0

在 Rails 中编写“(x AND y)OR(a AND b)”查询的最佳方法是什么?

我刚刚编写了以下消息方法来返回两个用户之间的消息。选择是在两个用户之间获取消息,即给我消息从我给他们他们给我

它有效,但看起来很可怕。有没有更简单/更好的写法?

class Conversation
  def initialize(me, them)
    @me = me
    @them = them
  end

  def messages
    t = Message.arel_table
    results = Message.where(
      (t[:sender_id].eq(@me.id).and(t[:recipient_id].eq(@them.id))).or(
      t[:sender_id].eq(@them.id).and(t[:recipient_id].eq(@me.id)))
    )
  end
end

注意感谢吉米,我最终得到了:

class Conversation
  def initialize(me, them)
    @me = me
    @them = them
  end

  def messages
    me_to_them = "sender_id = :my_id AND recipient_id = :their_id"
    them_to_me = "sender_id = :their_id AND recipient_id = :my_id"
    Message.where(
      "#{me_to_them} OR #{them_to_me}",
      {:my_id => @me.id, :their_id => @them.id}
    )
  end
end
4

3 回答 3

1

您可以通过使用 SQL 字符串和值插值的数组语法来稍微清理一下:

class Conversation < ActiveRecord::Base
  def initialize(me, them)
    @me = me
    @them = them
  end

  def messages
    Message.where(["(sender_id = ? AND recipient_id = ?) OR (sender_id = ? AND recipient_id = ?)", @me.id, @them.id, @them.id, @me.id])
  end
end
于 2012-03-25T10:11:56.997 回答
0

I had the same problem. I was searching the web for some hours and finally found a method named grouping in Arel::FactoryMethods which simply adds brackets around an expression.

With this your method should look like this:

def messages
  t = Message.arel_table
  results = Message.where(
    t.grouping(t[:sender_id].eq(@me.id).and(t[:recipient_id].eq(@them.id))).or(
    t.grouping(t[:sender_id].eq(@them.id).and(t[:recipient_id].eq(@me.id))))
  )
end
于 2013-03-01T16:39:55.460 回答
0

我之前已经建立了一个类似的系统。我的数据库的结构有点不同,但是为了使查询更简单,并允许进行群组对话(超过 2 人)

private_message_groups 
id | subject

private_message
id | group_id | private_message_group_id | user_id | message

private_message_follow
group_id | user_id | visible 

这样,您可以简单地将用户指向 private_message 控制器。如果你想让我更深入我可以,但这个系统的最大优势是现在你有一个论坛系统。

于 2012-03-23T18:03:51.087 回答