Ruby on Rails动态组合作用域



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

last scope, checked_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_的图书?在这种情况下,我希望条件数组包含"expired"one_answers"checked_out_by"作用域,但我不知道如何使用lambda作用域设置它。I tried:

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

,但这给了我一个错误说"{:checked_out_by => 6} is not a symbol"。我也试过

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

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

可以将参数作为第二个参数发送给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

或者,更好的是,创建一个类,其中包含您需要的键和值。

最新更新