重用named_scope来定义另一个named_scope

时间:2010-03-14 20:31:56

标签: ruby-on-rails activerecord named-scope searchlogic

我看到的问题本质

有一天,如果我没弄错的话,我已经看到了重用named_scope来定义另一个named_scope的例子。这样的事情(不记得确切的语法,但这正是我的问题):

named_scope :billable, :conditions => ...
named_scope :billable_by_tom, :conditions => {
    :billable => true, 
    :user => User.find_by_name('Tom')
}

问题是:如果可能的话,确切的语法是什么?我找不回来了,谷歌也没有帮助。

一些解释

为什么我真的想要它,是因为我使用Searchlogic来定义复杂的搜索,这可能会产生这样的表达式:

Card.user_group_managers_salary_greater_than(100)

但是到处都是太久了。因为据我所知,Searchlogic只是动态定义了named_scopes,我想在Card类上设置一个named_scope,如下所示:

named_scope from_big_guys, { user_group_managers_salary_greater_than(100) }

- 这是我在named_scope中使用那个漫长的Searchlogic方法的地方。但是,再次,语法是什么?无法理解。

恢复

那么,named_scope嵌套(并且意味着链接)实际上是否可能?

5 个答案:

答案 0 :(得分:7)

您可以使用 proxy_options 将一个named_scope回收到另一个:

class Thing
  #...
  named_scope :billable_by, lambda{|user| {:conditions => {:billable_id => user.id } } }
  named_scope :billable_by_tom, lambda{ self.billable_by(User.find_by_name('Tom').id).proxy_options }
  #...
end

这样它就可以与其他named_scopes链接。

我在我的代码中使用它,它完美无缺。

我希望它有所帮助。

答案 1 :(得分:2)

Rails 3 +

我有同样的问题,好消息是在过去的五年里,Rails核心团队在范围部门取得了一些进展。

在Rails 3+中,你现在可以做到这一点,正如你所期望的那样:

scope :billable,        where( due: true )
scope :billable_by_tom, -> { billable.where( user: User.find_by_name('Tom') ) }

Invoice.billable.to_sql         #=> "... WHERE due = 1 ..."
Invoice.billiable_by_tom.to_sql #=> "... WHERE due = 1 AND user_id = 5 ..."

仅供参考,Rails 3+他们已将named_scope重命名为scope。我也使用Ruby 1.9语法。

奖金回合:通用范围。

如果有多个人是"可计费"除了汤姆"那么创建一个接受传递给块的名称参数的通用范围可能是有用的:

scope :billable_by, lambda { |name| billable.where( user: User.find_by_name( name ) ) }

然后你可以用:

来调用它
Invoice.billable_by( "Tom" ).to_sql #=> "... WHERE due = 1 AND user_id = 5 ..."

顺便说一句,你可以看到我在奖励回合中使用了较旧的lambda语法。这是因为我认为当您将一个参数传递给它时,新语法看起来很残忍:->( name ) { ... }

答案 2 :(得分:1)

请参阅此前question提出的时间。 lighthouse有一个补丁来满足您的要求。

答案 3 :(得分:1)

Chain Scopes。

为什么一般只有scope的{​​{1}}内容为Tom,例如:

scope :by_tom, where( user: User.find_by_name('Tom') )

然后你就可以得到汤姆"可以收费的那些记录。用:

Record.billable.by_tom

答案 4 :(得分:0)

您可以使用方法组合一些named_scope,如:


def self.from_big_guys
  self.class.user_group_managers_salary_greater_than(100)
end

此功能在Rails 3上添加了新语法(http://m.onkey.org/2010/1/22/active-record-query-interface