我希望能够在运行时动态组合范围,以根据用户输入创建自定义查询。假设我有一个带有Book模型的库应用程序,并且我定义了以下范围:checked_out, fiction, non_fiction, overdue, and checked_out_by
。
last scope
,checked_out_by
是一个lambda,它将library_user_id作为参数。该应用程序允许库管理器根据用户输入运行不同类型的查询,这些查询动态组合这些范围。因此,如果图书管理员想要创建一个显示所有非小说类书籍的报告,那么很容易做到这样的事情:
criteria = ["non_fiction", "checked_out"] <= array built based on what the user selected
books = Book.scoped
criteria.each {|criteria| books = books.send(criteria)}
但是我如何使用设置为lambda的范围来做到这一点?例如,如果用户想要创建一个查询,显示过期的书籍和特定人员的check_out_by?在这种情况下,我希望criteria数组包含“overdue”和“checked_out_by”范围,但我无法弄清楚如何使用lambda范围设置它。我试过了:
criteria = ["non_fiction", {:checked_out_by => 6}]
但是这给了我一个错误“{:checked_out_by => 6} is not a symbol
”。我也试过
criteria = ["non_fiction", [checked_out_by, 6]]
以及其他一些变体,但都没有奏效。有谁知道怎么做?
答案 0 :(得分: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
或者,更好的是,创建一个具有您需要的键和值的类。