合并具有相同模型的两个has_many关联的结果

时间:2012-07-14 17:53:33

标签: ruby-on-rails

我有用户。用户可以戳戳其他用户,也可以自己动手。每个戳都是方向性的,并且不存在组戳。我想列出给定用户的所有戳(传入或传出),而不重复自我戳(作为incoming_和outgoing_pokes存在)。

以下是我的模特:

class User < ActiveRecord::Base
  has_many :outgoing_pokes, :class_name => "Poke", :foreign_key => :poker_id
  has_many :incoming_pokes, :class_name => "Poke", :foreign_key => :pokee_id
end

class Poke < ActiveRecord::Base
  belongs_to :poker, :class_name => "User"
  belongs_to :pokee, :class_name => "User"
end

我尝试在User模型中创建一个合并戳的方法:

def all_pokes
  outgoing_pokes.merge(incoming_pokes)
end

但是只返回self-pokes(那些是incoming_和outgoing_pokes)。想法?是否有一种干净的方法直接使用关联?

此外,在合并列表中,每个poke都有两个布尔值可以记录它们与当前用户的关系。类似于outgoingincoming

2 个答案:

答案 0 :(得分:11)

您的all_pokes方法仅返回自我戳的原因是因为outgoing_pokes还不是数组,而是您可以链接的AR关系。在这种情况下,merge在执行查询之前将它们组合在一起。

您想要的是实际执行查询并合并结果集:

def all_pokes
  (outgoing_pokes.all + incoming_pokes.all).uniq
end

...或者您可以编写自己的查询:

def all_pokes
  Poke.where('poker_id = ? OR pokee_id = ?', id, id)
end

确定是传入还是传出:

# in poke.rb
def relation_to_user(user)
  if poker_id == user.id
    poker_id == pokee_id ? :self : :poker
  elsif pokee_id == user.id
    :pokee
  else
    :none
  end
end

答案 1 :(得分:1)

现在Rails 5有OR个查询,有一个非常易读的解决方案。

def pokes
  outgoing_pokes.or(incoming_pokes)
end

我在方法名称中省略了all,因为它现在返回一个ActiveRelation,其他方法可以被链接。

@user.pokes.where(...).includes(...)