0

I have a users table and a blocked_users table. users has all my authentication data, site preferences, etc, and blocked_users has a source_id and a target_id.

I would like to return a collection of all users that a user has not blocked and that have not blocked the current user.

Right now I have the following code which I execute by calling @user.available_users but it executes three queries. Is there some way to make this a single query?

class User < Sequel::Model

  one_to_many :blocked_users,     :key=>:source_id
  one_to_many :blocked_by_users,  :key=>:target_id, :class => BlockedUser

  def block_user(id)
    BlockedUser.create({source_id:self.id, target_id:id})
  end 

  def blocked_user_ids
    self.blocked_users.map{|bu| bu[:target_id]}
  end 

  def blocked_by_user_ids
    self.blocked_by_users.map{|bu| bu[:target_id]}
  end 

  def available_users
    User.exclude(:id=>self.blocked_users.map{|bu| bu[:target_id]}).exclude(:id=>self.blocked_by_users.map{|bu| bu[:target_id]})
  end 
end

I added the following method to my User class:

  def test_avail
    User.exclude(:blocked_users=>self).exclude(:blocked_by_users=>self)
  end 

1.9.3p0 :001 > User.all.first.test_avail
   INFO - (0.000732s) SELECT * FROM `users`
Sequel::Error: invalid association class User for association :blocked_users used in dataset filter for model User, expected class BlockedUser
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
jdkealy
  • 4,807
  • 6
  • 34
  • 56

1 Answers1

2

Using filter by associations support is probably easiest:

def available_users
  User.exclude(:blocked_users=>self).exclude(:blocked_by_users=>self)
end
Jeremy Evans
  • 11,959
  • 27
  • 26
  • Hey so I added the changes in the above question but now with that snippet I get Sequel::Error: invalid association class User for association :blocked_users used in dataset filter for model User, expected class BlockedUser – jdkealy Jun 28 '12 at 19:13
  • My bad. The code would work if blocked_users and blocked_by_users were self referential many_to_many associations. Instead, you are using a separate BlockedUser class and one_to_many associations. I'm not sure why you set it up that way. With your current code, you should be able to do User.exclude(:id=>self.blocked_users_dataset.select(:target_id)). – Jeremy Evans Jun 28 '12 at 23:01