我试图使用ransack按年龄过滤结果,但是ransack给了我一个未定义的方法错误。我在我的数据库中有用户DOB,在我的用户模型中,我有一个计算用户年龄的年龄方法。它工作得非常好,我能够像这样称呼用户年龄:
@user = User.find(1)
@user.age
现在我的控制器中有以下内容:
def index
@search = User.search(params[:q])
@users = @search.result
end
在我看来,我有:
<%= search_form_for @search do |f| %>
<%= f.label :age_gteq, "Ages:" %> <%= f.text_field :age_gteq %>
<%= f.label :age_lteq, "to" %> <%= f.text_field :age_lteq %>
<%=f.submit "Filter", class: "button" %>
<% end %>
这是我得到的错误:
undefined method `age_gteq' for Ransack::Search<class: User, base: Grouping <combinator: and>>:Ransack::Search
我确信age_lteq
答案 0 :(得分:3)
据我所知,它不起作用,因为目前Ransack只适用于数据库列。最后,Ransack只是一个复杂的SQL查询生成器。
想想这个例子:
User.where('age >= ?', 30)
SQL查询会是什么样的?
SELECT * FROM user WHERE age >= 30
即使Ransack会在正常的非数据库属性上管理这些条件,SQL仍然是错误的。 (因为没有age
列)
一种解决方案是使用表单中的原始出生日期列并使用一些Javascript来允许用户输入年龄数而不是日期。例如,通过收听onsubmit
事件并修改input
的内容。
更新2014-01-08:
还有另一种可能性使这项工作成功。将其添加到您的User
模型中:
ransacker :age do
Arel::Nodes::SqlLiteral.new(
'DATE_PART('year', AGE(NOW(), date_of_birth_column))')
# Beware: PostgreSQL specific SQL!
end
“ransacker”需要返回一个Arel节点,该节点稍后将附加到由Ransack生成的Arel节点上。
这允许您使用age_eq
和所有其他Ransack谓词,就像它是常规数据库列一样。