views:

21

answers:

1

User model:

class User < ActiveRecord::Base
  named_scope :clients, 
    :conditions => "roles_users.role_id = #{Role.find_by_name('client').id}"
end

When testing, throws error:

Called id for nil, which would mistakenly be 4 -- if you really wanted (etc.)

Role fixtures:

client:
  name: client
user:
  name: user

Apparent problem: Rails is loading this class before it loads fixtures. When it loads the class it evaluates the named_scope. There are no roles at that point, so it blows up.

Possible solution:

named_scope :clients, 
  lambda { { :conditions => "roles_users.role_id = #{Role.named('client').id}" } }

However, I am not pleased with this solution, seeing as it introduces additional complexity and presumably a (small?) performance hit, just so that tests run properly. I'd like an alternative. Can you help?

+1  A: 

The solution you propose is the correct solution. I would also recommend changing your code to:

named_scope :clients, lambda { { :conditions => ['roles_users.role_id = ?', Role.named('client').id } }

An alternative might be:

named_scope :clients, :joins => :role, :conditions => ['roles.name = ?', 'client']

You might also want to think about doing:

named_scope :with_role, lambda { |r| { :conditions => ['roles_users.role_id = ?', r.id] } }

Or even (for extra points)

Role.find_by_name('client').users

Anyway, I hope this helps.

jonnii
Thanks. I understand your first recommendation (security/correctness). But what do you see as the advantage of your second suggestion, the one with :joins => :role? Is it simply for clarity's sake?
adriandz
It would achieve the same thing in one query, instead of two.
jonnii