将named_scope转换为rails 3

时间:2010-10-26 15:04:26

标签: ruby-on-rails

我有以下代码,它引发了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

调用时出现以下错误:

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

正如你所看到的那样,user_id现在是一个包含ActiveRelation对象的表,而且......我的user_id

我不明白发生了什么......你有什么想法吗?

由于

更新:这是完整的SQL输出:

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:这是调用我的范围的代码https://gist.github.com/ddddfeddf70264a81289

update3:正如您在我的要点中所看到的那样,通过“调用”调用链式范围:

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

如果我记录发送的user_id,则它是一个FixNum而不是一个数组:

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

所以问题现在更加精确了:我将一个Fixnum作为参数发送到我的named_scope但输出了一个类型的数组:[ActiveRecord :: Relation,FixNum]

update4:我终于找到了解决方案(但不知道为什么???)

我用“发送”替换了“call”,它有效......

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

感谢大家的帮助!

1 个答案:

答案 0 :(得分:2)

试试这个:

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)
}

顺便说一句,可能是这里有一个逗号丢失了,有什么东西应该在audition_tags和bar之间吗?

FROM audition_tags bar

而且根据你的错误,我认为你传入的是一个用户对象 - 而不是ID,请记住在Rails 3中,一切都是ActiveRecord关系,所以你必须调用firstall关系首先得到一个结果。

示例:

user = User.where('conditions').first
Auditions.not_rated_by(user.id)