views:

46

answers:

1

I have the following code wich throws an error with Rails 3 :

module Auditions
  module Search
     def self.included(base)
        base.extend ClassMethods
        ...
        base.named_scope :not_rated_by, lambda { |user_id| {
          :conditions => ['NOT EXISTS (SELECT * FROM audition_tags bar WHERE bar.user_id = ? AND bar.audition_id = auditions.id)', user_id]
        }}
        ...
     end
  end
end

When called the following error appears :

Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '2053809816 AND audition_tags.audition_id = auditions.id)) ORDER BY  auditions.cr' at line 1: SELECT     `auditions`.* FROM       `auditions`  WHERE     (NOT EXISTS (SELECT * FROM audition_tags WHERE audition_tags.user_id = '#<ActiveRecord::Relation:0x104ee3c20>',2053809816 AND audition_tags.audition_id = auditions.id)) ORDER BY  auditions.created_at DESC LIMIT 0, 10

As you can see it's like user_id is now a table containing an ActiveRelation object and well ... my user_id

I don't understand what's going on ... do you have an idea ?

Thanks

update : here's the complete SQL output :

SELECT `auditions`.* FROM `auditions` WHERE (NOT EXISTS (SELECT * FROM audition_tags as bar WHERE bar.user_id = '#<ActiveRecord::Relation:0x104aa6c48>',2053809816 AND bar.audition_id = auditions.id)) ORDER BY auditions.created_at DESC LIMIT 0, 10

update2 : here's the code calling my scope https://gist.github.com/ddddfeddf70264a81289

update3 : as you can see in my gist the chained scopes are called with a "call" :

scopes.inject(self) {|m,v| m.scopes[v[0]].call(m, v[1]) }

If I log the user_id sent it's a FixNum not an Array :

scopes.inject(self) do |m,v| 
  logger.info ">>> SCOPE : #{v[0].inspect} | ARG : #{v[1].inspect} | ARG CLASS : #{v[1].class.inspect} <<<"
  m.scopes[v[0]].call(m, v[1])
end

So the problem is more precise now : I send a Fixnum as argument to my named_scope but got on output an Array of type : [ActiveRecord::Relation, FixNum]

update4 : I finally find the solution (but not sure why ???)

I replaced "call" by "send" and it works ...

results = scopes.inject(self) do |combined_scope, scope|
  combined_scope.send(scope[0], scope[1])
end

Thanks all for your help !

+1  A: 

Try this:

scope :not_rated_by, lambda { |user_id| {
  where('NOT EXISTS (SELECT * FROM audition_tags bar WHERE bar.user_id = ? AND bar.audition_id = auditions.id)', user_id)
}

And by the way, could it be that there is a comma missing here, something should go bewtween audition_tags and bar?

FROM audition_tags bar

And also based on your error I think you are passing in a user object - not a ID, remember in Rails 3 everything is a ActiveRecord Relation so you have to call first or all on the relation first to get a result.

Example:

user = User.where('conditions').first
Auditions.not_rated_by(user.id)
Max Schulze
Hi Max I tried to convert my named_cope to the scope you mentioned but I got the same exact error. For "FROM audition_tags bar" you can check the SQL syntax it's equivalent to "FROM audition_tags AS bar" and no I'm passing a user_id not an object that's the weird thing (I even inspected it and before going into the scope it's a FixNum) ...
Mike
'#<ActiveRecord::Relation:0x104aa6c48>',2053809816 does look like your passing something not integer in?
Max Schulze
I updated the question
Mike
What happens if you (in your scope), put user_id.last in their, just for debugging, it should take the last key of the array which is the fixnum, as we can see from your test.
Max Schulze