查找条件不在数组中的所有匹配条件

时间:2012-12-12 04:51:01

标签: sql ruby-on-rails-3 associations

我试图返回一个包含用户数组值的变量。必须满足一些条件。用户必须将public_find设置为true,它不能是current_user(当前登录用户的会话变量),并且它必须不是友谊的一部分。第一和第二个条件完美地运作。但是,我遇到第三部分的问题,其中current_users.friendships需要是已存在关联的用户的ID值的数组。有什么想法吗?

@users = User.find(:all, :conditions => ['
    public_find=true AND 
    id <> ? AND 
    id NOT IN (?)',
    current_user.id, current_user.friendships])

编辑:

我已经发现我从列表中删除了。这现在很好用。但是,如果某人还没有朋友,则current_user.friendships.pluck(:friend_id)将返回NULL。我知道使用NOT INNULL时这是不好的做法和意外结果。但是,如果返回的数组为空,如何创建一个可以将值设置为[0]或[1]之类的条件的条件?

@users = User.find(:all, :conditions => ['
    public_find=true AND 
    id <> ? AND 
    id NOT IN (?)',
    current_user.id, current_user.friendships.pluck(:friend_id) || [0]])

再次编辑:

我得到了它的工作。但是,现在我想知道这是否是最好的做法。它基本上是检查current_user.friendships.pluck(:friend_id)是否为空。如果是则返回[0]。否则返回用户id的数组(外键为friend_id)。

@users = User.find(:all, :conditions => ['
    public_find=true AND 
    id <> ? AND 
    id NOT IN (?)',
    current_user.id, 
    (current_user.friendships.pluck(:friend_id).empty? ? [0] : current_user.friendships.pluck(:friend_id))])

2 个答案:

答案 0 :(得分:1)

你可以写得更好......

显示public_find为true的所有用户,并排除当前登录的用户或他们的任何朋友

ids = current_user.friendships.map(&:friend_id).concat([current_user.id])
@users = User.where(:public_find => true).where('id not in ?', ids) 

答案 1 :(得分:1)

我会使用一个arel表(这可以保证代码可以在任何数据库上运行):

t, f = User.arel_table, current_user.friendships
query = t[:public_find].eq(true).and(t[:id].not_eq(current_user.id))
query = query.and(t[:id].not_in(f.pluck(:friend_id))) unless f.empty?
@users = User.where(query)

current_user = 3生成的SQL以及与id = 1用户的单一友谊:

SELECT "users".* FROM "users"
WHERE ("users"."public_find" = 't' AND "users"."id" != 3 AND "users"."id" NOT IN (1))

如果current_user.friendshipsnilunless f.empty?子句将阻止该条件被应用,因此它不会出现在SQL中:

SELECT "users".* FROM "users"
WHERE ("users"."public_find" = 't' AND "users"."id" != 3)

另请注意,由于此代码使用where而非find,因此最终结果为ActiveRecord::Relation而不是结果数组。这意味着您可以进一步将条件链接到其上,例如要按updated_at订购结果,请将最后一行更改为:

@users = User.where(query).order(:created_at)