views:

182

answers:

1

I'm hoping I'm doing something wrong here and someone can point me in the right direction...

I have written a method inside of one of my models, here is the code:

def self.find_by_user_id(user_id, *args)
    self.find(:all, :joins => :case_map,
       :conditions => ['case_maps.uer_id = ? and case_maps.case_id = cases.id', user_id], 
        *args)
end

I can call the code like this and it works as expected:

Case.find_by_user_id(some_user_id)

However, when this code is executed with any additional args, like this:

Case.find_by_user_id(some_user_id, :limit => 15)

I get back ALL cases. The query in my log file show that it executed this:

Case Load (0.6ms)   SELECT * FROM `cases` LIMIT 15

I even put a logger.info message in that method to make sure it's the one that is executing... It seems that whenever *args is not nil, that it skips all of the conditions and joins I added to the find and just uses the *args.

Anyone see something that I'm doing wrong?

+3  A: 

AR::B#find expects a variable number of arguments, but the last of those should be the options hash. It uses Array#extract_options!, and so can you:

def self.find_by_user_id(user_id, *args)
  options = args.extract_options!
  options.merge!(:joins => :case_map, :conditions => 
    ['case_maps.uer_id = ? and case_maps.case_id = cases.id', user_id])
  self.find(:all, *args, options)
end

But you shouldn't. What possible values make sense in between the :all and the options fields?

What you are really after is:

def self.find_by_user_id(user_id, options)
  self.find(:all, options.merge(:joins => :case_map, :conditions => 
    ['case_maps.user_id = ? and case_maps.case_id = cases.id', user_id]))
end

Or one better:

named_scope :find_by_user_id, lambda{|user_id|
  {
    :joins => :case_map,
    :conditions => ['case_maps.user_id = ? and case_maps.case_id = cases.id', user_id]
  }
}

The named scope will ensure all your options are cleanly merged (all your conditions are applied even if you add more later on). You can then call it with:

Case.find_by_user_id(user_id).all(:limit => 15)

(Named Scope are “Da Bom”. One should use them as much as possible. Even in general conversation. For example, if you were here in my house last night, you may have overheard this little ditty: “What do you want for your dinner?”, “Same thing I have every night, Named Scopes and chips.”. Because I'm committed and all that.)

Also, as a side note, assuming this is on your Case model, the "and case_maps.case_id = cases.id" clause is unnecessary, :joins => :case_map does that for you.

cwninja
Perfect. Exactly what I needed. Thanks for the clarity.
intargc