问题描述
将 Rails 2 应用程序转换为 Rails 3,我必须替换 gem searchlogic.现在,使用 Rails 3.2.8 和 gem Ransack 我想构建一个使用现有范围的搜索表单.示例:
Converting a Rails 2 application to Rails 3, I have to replace the gem searchlogic. Now, using Rails 3.2.8 with the gem Ransack I want to build a search form which uses an existing scope. Example:
class Post < ActiveRecord::Base
scope :year, lambda { |year|
where("posts.date BETWEEN '#{year}-01-01' AND '#{year}-12-31'")
}
end
据我所知,这可以通过定义自定义ransacker来实现.可悲的是,我没有找到任何关于此的文档.我在 Post
类中试过这个:
So far as I know, this can be achieved by defining a custom ransacker. Sadly, I don't find any documentation about this. I tried this in the Post
class:
ransacker :year,
:formatter => proc {|v|
year(v)
}
但这不起作用:
Post.ransack(:year_eq => 2012).result.to_sql
=> TypeError: Cannot visit ActiveRecord::Relation
我尝试了 ransacker
声明的一些变体,但它们都不起作用.我需要一些帮助...
I tried some variations of the ransacker
declaration, but none of them work. I Need some help...
更新:以上范围仅作为示例.我正在寻找一种方法来使用 Ransack 中的每个现有范围.在 Ransack 的前身 MetaSearch 中,有一个名为 search_methods
的功能,用于使用范围.Ransack 尚未对此不提供支持.
UPDATE: The scope above is just on example. I'm looking for a way to use every single existing scope within Ransack. In MetaSearch, the predecessor of Ransack, there is a feature called search_methods
for using scopes. Ransack has no support for this out of the box yet.
推荐答案
ransack 在合并 https://github.com/activerecord-hackery/ransack/pull/390.你应该声明 ransakable_scopes 方法来添加对ransack可见的范围.
ransack supports it out of the box after merging https://github.com/activerecord-hackery/ransack/pull/390 . you should declare ransakable_scopes method to add scopes visible for ransack.
来自手册
继续上一节,按范围搜索需要在模型类上定义一个 ransackable_scopes 白名单.白名单应该是一个符号数组.默认情况下,所有类方法(例如范围)都将被忽略.范围将应用于匹配真实值,或者如果范围接受值,则应用于给定值:
Continuing on from the preceding section, searching by scopes requires defining a whitelist of ransackable_scopes on the model class. The whitelist should be an array of symbols. By default, all class methods (e.g. scopes) are ignored. Scopes will be applied for matching true values, or for given values if the scope accepts a value:
class Employee < ActiveRecord::Base
scope :activated, ->(boolean = true) { where(active: boolean) }
scope :salary_gt, ->(amount) { where('salary > ?', amount) }
# Scopes are just syntactical sugar for class methods, which may also be used:
def self.hired_since(date)
where('start_date >= ?', date)
end
private
def self.ransackable_scopes(auth_object = nil)
if auth_object.try(:admin?)
# allow admin users access to all three methods
%i(activated hired_since salary_gt)
else
# allow other users to search on `activated` and `hired_since` only
%i(activated hired_since)
end
end
end
Employee.ransack({ activated: true, hired_since: '2013-01-01' })
Employee.ransack({ salary_gt: 100_000 }, { auth_object: current_user })
这篇关于Ransack:如何使用现有范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!