12

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

这是我的模型:

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

但这只返回自戳(那些既是incoming_又是outgoing_pokes)。想法?有没有一种直接使用关联的干净方法?

此外,在合并列表中,最好为每个 poke 设置两个布尔值来记录它们与当前用户的关系。outgoing类似于和的东西incoming

4

2 回答 2

12

您的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
于 2012-07-14T18:03:47.103 回答
12

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

def pokes
  outgoing_pokes.or(incoming_pokes)
end

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

@user.pokes.where(...).includes(...)
于 2018-05-22T13:08:35.860 回答