使用Ransack gem按年龄过滤的未定义方法错误

时间:2013-04-06 10:07:40

标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.1 ruby-on-rails-3.2 ransack

我试图使用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

会出现同样的错误

1 个答案:

答案 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谓词,就像它是常规数据库列一样。