【问题标题】:Ruby on Rails combining scopes dynamicallyRuby on Rails 动态组合范围
【发布时间】:2013-03-29 22:04:07
【问题描述】:

我希望能够在运行时动态组合范围,以根据用户输入创建自定义查询。假设我有一个带有 Book 模型的库应用程序,并且定义了以下范围:checked_out, fiction, non_fiction, overdue, and checked_out_by

last scopechecked_out_by 是一个将 library_user_id 作为参数的 lambda。该应用程序允许图书馆员根据用户输入运行不同类型的查询,动态组合这些范围。因此,如果图书管理员想要创建一份报告,显示所有已签出的非小说类书籍,则可以轻松执行以下操作:

criteria = ["non_fiction", "checked_out"]  <= array built based on what the user selected  
books = Book.scoped  
criteria.each {|criteria| books = books.send(criteria)}  

但是如何使用设置为 lambda 的范围来执行此操作?例如,如果用户想要创建一个查询,显示某个特定人已过期和已签出的书籍?在这种情况下,我希望条件数组包含“过期”和“checked_out_by”范围,但我不知道如何使用 lambda 范围进行设置。我试过了:

criteria = ["non_fiction", {:checked_out_by => 6}]  

但这给了我一个错误,说“{:checked_out_by =&gt; 6} is not a symbol”。我也试过了

criteria = ["non_fiction", [checked_out_by, 6]]

和其他一些变体,但它们都不起作用。有人知道怎么做吗?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 activerecord dynamic-scope


    【解决方案1】:

    您可以将参数作为第二个参数发送到send。基于您的示例,您可以执行以下操作:

    criteria = [:non_fiction, { checked_out_by: 6 }]
    
    criteria.each do |c|
      case c
        when Hash then c.keys.each { |key| books = books.send key, c[key] }
        when Symbol then books = books.send c
      end
    end
    

    或者您可以使用OpenStruct 代替Hash

       criteria = [:non_fiction, OpenStruct.new(key: :checked_out_by, value: 6)]
    
       criteria.each do |c|
          books = case c
            when OpenStruct then books.send c.key, c.value
            when Symbol then books.send c
          end
        end
    

    或者,更好的是,创建一个具有您需要的键和值的类。

    【讨论】:

    • 谢谢,很好的建议。我做了第一个,它解决了问题。
    猜你喜欢
    • 2012-03-15
    • 1970-01-01
    • 2018-03-23
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-17
    • 1970-01-01
    相关资源
    最近更新 更多