我想使用ransack为Users
的网页构建高级搜索功能。
我有一个小方法来计算从出生日期开始的年龄:
def age(dob)
now = Time.now.utc.to_date
now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
end
适用于正常显示(as in age(@user.date_of_birth)
)
但是当使用search_form_for时我不能这样做:
<%= search_form_for @search, url: search_users_path, method: :post do |f| %>
<div class="field">
<%= f.label :date_of_birth_gteq, "Age between" %>
<%= f.text_field :date_of_birth_gteq %>
<%= f.label :date_of_birth_gteq, "and" %>
<%= f.text_field :date_of_birth_lteq %>
</div>
<div class="actions"><%= f.submit "Search" %></div>
<% end %>
我的问题是:如何在搜索中使用年龄而不是出生日期?
答案 0 :(得分:4)
添加如下所示的范围,以查找给定年龄的日期。
scope :age_between, lambda{|from_age, to_age|
if from_age.present? and to_age.present?
where( :date_of_birth => (Date.today - to_age.to_i.year)..(Date.today - from_age.to_i.year) )
end
}
对于ransacke语法:
ransacker :age, :formatter => proc {|v| Date.today - v.to_i.year} do |parent|
parent.table[:date_of_birth]
end
在视图中
<%= f.text_field :age_gteq %>
答案 1 :(得分:2)
我个人并不认识ransacker,并试图使用ransacker,但无法找到任何能够检查谓词的内容。 因此,我认为使用范围更好。
def self.age_lteq(age)
start_birth_year = Date.today.year - age
where('date_of_birth >= ?', Date.new(start_birth_year))
end
def self.age_gteq(age)
birth_year = Date.today.year - age
end_of_birth_year = Date.new(birth_year + 1) - 1
where('date_of_birth <= ?', end_of_birth_year)
end
private
def self.ransackable_scopes(auth_object = nil)
%i(age_lteq age_gteq)
end
# In views just do the following (ransack default grouping queries is by AND)
# https://github.com/activerecord-hackery/ransack#grouping-queries-by-or-instead-of-and
<%= f.input :age_lteq %>
<%= f.input :age_gteq %>
@siddick的答案很酷,但lteq
的行为与gt
和gteq
的行为类似lt
。
我自己最近开始使用ruby和rails。所以告诉我,如果我做错了什么。 :)
谢谢!
答案 2 :(得分:1)
关于@siddick答案的更新(完美无缺)。您现在需要使用ransack提供的白名单范围。如果是@siddick的回答你需要这样做:
def self.ransackable_scopes(auth_object = nil)
%i(age_between)
end
有关详细信息,请参阅文档 - https://github.com/activerecord-hackery/ransack#using-scopesclass-methods