首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ActiveRecord named_scope,.scopes

ActiveRecord named_scope,.scopes
EN

Stack Overflow用户
提问于 2009-10-20 22:03:13
回答 1查看 2K关注 0票数 3

这个问题的背景是相当复杂和令人费解的,由于我正在寻找一个简单的答案,我将把它放在一边来解释我的问题,而不是提供这个假设的情况。

如果我有一个简单的ActiveRecord模型,叫做汽车,它的named_scopes如下:

代码语言:javascript
复制
named_scope :classic, :conditions => { :build_date <= 1969 }
named_scope :fast, lambda { |speed| :top_speed >= speed }

忽略作用域本身,如果我调用:

代码语言:javascript
复制
Automobile.scopes

这到底会返回什么呢?我在控制台中看到的是:

代码语言:javascript
复制
[ :classic => #<Proc:0x01a543d4@/Users/user_name/.gem/ruby/1.8/gems/activerecord-2.3.4/lib/active_record/named_scope.rb:87>,
  :fast => #<Proc:0x01a543d4@/Users/user_name/.gem/ruby/1.8/gems/activerecord-2.3.4/lib/active_record/named_scope.rb:87> ]

在我看来,这是一个键/值的数组,键是命名作用域的符号,值是指向ActiveRecord中的named_scope.rb文件的进程。

如果我想要给定的散列或Proc作为实际的命名作用域(对于:classic,我会收到":conditions => { :build_date <= 1969 }",我该如何找到它?

我正在写一个有条件地合并一些named_scopes的插件,在这方面我遇到了一些阻力。我目前正在使用以下内容来合并这些作用域:

代码语言:javascript
复制
scopes_to_use = Automobile.scopes
scoped_options = {}
Automobile.scopes.each do |scope|
    scoped_options.safe_merge!(eval "Automobile.#{scope}(self).proxy_options")
end

忽略我在这里所做的“正确性”,有没有更好的方法可以检索给named_scope的实际散列或Proc?我不喜欢在这个函数中使用'eval‘,如果我真的可以检索Hash或Proc,那么我就可以引入一些更强大的合并逻辑。任何关于这方面的想法都将不胜感激。谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2009-10-21 12:52:55

您在示例中定义的命名作用域都不会执行任何操作。他们在句法上是错误的。这可能会导致您可能遇到的问题。

假设示例是仓促创建的,并且您已经有了可用的示例。继续回答这个问题。

我该如何找到作为实际命名作用域的散列或进程呢?

Model.scopes[:scope_name]为您提供了进程。Model.send(:scope_name).proxy_options为您提供了提供给作用域的选项散列,例如:{ :conditions => ["build_date <= ?", 1969] }

要以编程方式检索模型中每个命名作用域的选项散列,您可以这样做:

代码语言:javascript
复制
scopes_to_use = Automobile.scopes
scoped_options = {}
Automobile.scopes.keys.each do |scope|
    scoped_options.safe_merge!(Automobile.send(scope).proxy_options)
end

对于需要参数的作用域,这并不能很好地工作,因为它们可能会引发异常。不幸的是,我想不出一个简单的方法来解决这个问题。

我能想到的最好的办法是测试proc的一致性,然后提供唯一的伪参数,并分析返回的代理选项,以找出发生了什么变化。但这需要大量的工作,因为任何命名作用域的数量都是-2。在检索参数时,你能做的最好的就是调用proc,修复一个参数错误,并解析它以获得预期的一个或多个参数。然后使用该数量的伪参数。

整个过程需要一个救援块和一些评估魔法才能起作用。这是在您可以处理用于安全合并的proxy_options散列之前。

简而言之,你会想要做一些类似的事情,它不是很漂亮,但它是有效的:

代码语言:javascript
复制
scopes_to_use = Automobile.scopes
    scoped_options = {}
Automobile.scopes.each do |scope,proc|
  next if scope == :scoped
  number_of_args = 1
  begin
    scoped_options.safe_merge! Automobile.send(scope, "#{scope}_argument_1").proxy_options
  rescue 
    $!.to_s.match /(\d+)\)$/
    number_of_args = $1.to_i
    puts number_of_args
  end
     scoped_options.safe_merge!(Automobile.send(scope, *(1..number_of_args).map{|i| "#{scope}_argument_#{i}"}.proxy_options)
end

这应该是安全的,因为proxy_options既不执行SQL,也不进行任何类型检查。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1597581

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档