ransackを用いて年度検索を実装する.
動作デモはこちら.
前提条件
-
Ruby v2.4.0
-
Rails v5.0.2
-
nameとbirthayを持つUserを作成する.
rails g scaffold User name:string birthday:date
- gemを追加する.
Gemfile
gem 'ransack'
Nameで検索
名前文字列が含まれるかどうかで検索する.
:name_cont
の記述がそれに当たる.
app/controllers/users_controller.rb
def index
@q = User.ransack(params[:q])
@users = @q.result
end
app/views/users/index.html.erb
<%= search_form_for @q, url: :users do |f| %>
<%= f.label :name %>
<%= f.text_field :name_cont, placeholder: 'Name' %>
<br>
<%= f.submit 'Search' %>
<% end %>
これで生成されるSQLは下記の通り.
# @q.result.to_sql
SELECT "users".* FROM "users" WHERE ("users"."name" LIKE '%A%')
Birthdayを期間で検索
期間の開始・終了を両方選択させるパターン.
app/views/users/index.html.erb
<%= search_form_for @q, url: :users do |f| %>
<%= f.label :name %>
<%= f.text_field :name_cont, placeholder: 'Name' %>
<%= f.label :birthday %>
<%= f.date_field :birthday_gteq, include_blank: true %> 〜
<%= f.date_field :birthday_lteq, include_blank: true %>
<br>
<%= f.submit 'Search' %>
<% end %>
これで生成されるSQLは下記の通り.
birthday_gteq
が "birthday" >= '2017-03-01'
を指し, birthday_lteq
が "birthday" <= '2017-03-03'
を指す.
# @q.result.to_sql
SELECT "users".* FROM "users" WHERE ("users"."birthday" >= '2017-03-01' AND "users"."birthday" <= '2017-03-03')
Birthdayを年度で検索(年度を選択させるパターン)
期間の開始と終了をしていするのではなく,年度を一つだけ選択して検索したい.
Custom Predicate を作成して,年度(yyyy/04/01-yyyy+1/03/31)で絞込み出来るようにする.
config/initializers/ransack.rb
Ransack.configure do |config|
config.add_predicate :during_year,
arel_predicate: :between,
formatter: proc { |v|
Time.zone.parse("#{v.year}-4-1").to_date...Time.zone.parse("#{v.year + 1}-4-01").to_date
# または `..` で 4/1〜3/31 でもOK
# Time.zone.parse("#{v.year}-4-1").to_date..Time.zone.parse("#{v.year + 1}-3-31").to_date
},
type: :date
end
Custom Predicate は, <field name>_<custom_predicate_name>
で使用できる.
app/views/users/index.html.erb
<%= search_form_for @q, url: :users do |f| %>
<%= f.label :name %>
<%= f.text_field :name_cont, placeholder: 'Name' %>
<%= f.label :birthday %>
<%= f.date_field :birthday_gteq, include_blank: true %> 〜
<%= f.date_field :birthday_lteq, include_blank: true %>
<%= f.label :birthday_during_year %>
<%= f.date_select :birthday_during_year,
discard_day: true, discard_month: true,
include_blank: true %>
<br>
<%= f.submit 'Search' %>
<% end %>
これで生成されるSQLは下記の通り.
# @q.result.to_sql
SELECT "users".* FROM "users" WHERE ("users"."birthday" >= '2016-04-01' AND "users"."birthday" < '2017-04-01')
参考