某フリマサイトの検索まとめ(前編)
某フリマサイトのコピーをRailsにて作成した際にransackによる検索をする方法をまとめました
URL:https://github.com/yusuke-ishizaki/freemarket_sample_50b
Ransackによる条件検索
——————————————————
・必要なもの
Gem”ransack” gem”active hash”
—————————————————
・詳細検索作成手順
1. ransack 導入
2. コントローラー記述
3. フォーム制作
4. ActiveHash導入(gem,モデル)
5. ActiveHash導入(アソシエーション)
6. フォーム作成2
↓詳細
————————————————
1. Ransack 導入
gemfileに gem’ransack’記述
→bundle install
→rails s
2.コントローラーに記述
検索対象コントローラーにsearchアクションを作成
今回は ’products controller’
→検索オブジェクト作成
@search = Product.ransack(params[:q])
・@search…検索オブジェクト、検索するということの定義、名前なんでも良き
・.ransack…Productのデータを検索するよーという命令メソッド
・params[:q]…検索結果パラメータ、公式より:qにするみたい
→検索オブジェクト結果作成
@products = @search.result
・@products…検索結果オブジェクト、結果の定義、こっちをviewに反映する、名前なんでも良き
・.result…resultメソッド、検索オブジェクトの検索結果を出力する
→まとめ
class ProductController < ApplicationController
def search
@search = Product.ransack(params[:q])
@products = @search.result
end
●[product_controller.rb L64]
<おまけ>distinct: trueや.to_a.uniqを使うことで重複を避けることができる
@search.result(distinct: true) @search.result.to_a.uniq
3.フォーム雛形作成
通常の入力・検索フォームではform_with, form_for, form_tag使う”search_form_for”を用いる
“= search_form_for 検索オブジェクト, url: 検索結果表示ページのpath do |f| “
検索オブジェクトにはcontrollerで定義したもの(今回は@search)を用いる
パスは url: で結果表示先を示す
|f| はform_with系と同様に f.label のように使う
今回は “= search_form_for @search, url: search_product_index_path do |f|”
●[search.html.haml L5]
<おまけ> “= search_form_for(@q, format: :pdf) do |f|” “= search_form_for(@q, format: :json) do |f|” とすることで形式をpdfやjsonに指定できる
キーワード検索フォーム ransack版
“= search_form_for 検索オブジェクト, url: 検索結果表示ページのpath do |f| “のネスト中に
“= f.search_field :カラム_cont, class:クラス名”
search_field…検索入力バーを作成する
カラム_cont…指定カラムに対してLIKE句検索(あいまい検索)を行う
今回は “= f.search_field :name_cont, class: "search-box__detail-search__form-group__input"
●[search.html.haml L15]
★今回name_contとした理由…controllerで@search=Product.ransack とProductモデルに検索をかけるよう指定しているので “nameカラム”に”_cont”しても正確にProduct.nameを検索する(Brand.nameなど他のモデルには手を出さない)
<おまけ>複数カラムあいまい検索…= f.search_field :カラム1_or_カラム2_or_カラム3_cont(orのとこandでもおっけい) 1にname、2にstatus、3にtextなど
検索結果表示
” - @products.each do |product|”
検索結果の表示には、controllerにて定義した検索結果オブジェクト@products
検索結果をソートさせたい
“= sort_link(検索オブジェクト, :カラム, ‘ソートのラベル’, default_order: :desc)”
今回は”= sort_link(@search, :name, '名前順', default_order: :asc)”
●[search.html.haml L6]
価格帯検索したい
”= f.number_field :カラム_gteq, placeholder: 説明, class:クラス名”
”= f.number_field :カラム_lteq, placeholder: 説明, class:クラス名”
_gteq で~以上の検索
_lteq で~以下の検索
●今回は
”= f.number_field :price_gteq, placeholder: "¥ Min", class: "search-box__detail-search__form-group__price-min search-box__detail-search__form-group__input””
” = f.number_field :price_lteq, placeholder: "¥ Max", class: "search-box__detail-search__form-group__price-max search-box__detail-search__form-group__input””
[search.html.haml L32]
—————————————————————
追記
●今回使わなかったけどransackでできること
Predicate検索(カラム名と述語(Predicate)で検索する方法)
*_eq equal(=)を使った検索
*_matches LIKE検索
*_does_not_match LIKE検索で除外されるもの
*_cont LIKE検索(部分一致)
*_start LIKE検索(前方一致)
*_end LIKE検索(後方一致)
*_gt より大きい(>)検索
*_gteq 以上(>=)検索
*_lt より小さい(<)検索
*_lteq 以下(<=)検索
*_true trueのものを検索
*_false falseのものを検索
*_null null(存在しない)ものを検索
*_present present?メソッドに近い NULLでも空文字でもなければマッチ
*_blank blank?メソッドに近い NULLか空文字だったらマッチ
*_not_??? 述語の前にnotをつけることで、否定が可能
*_???_all 末尾にallをつけることで、複数の値に対してANDで連結して検索
*_???_any 末尾にanyをつけることで、複数の値に対してORで連結して検索
= f.attribute_fields do |a|
= a.attribute_select associations: [:アソシエーションしてるモデルのカラム]
でアソシエーションしてるモデルのカラムをセレクトに選ぶことができる
動的に追加されるフォームを作成する方法
・/app/helpers/application_helper.rbにlink_to_add_fieldsメソッドを作成
module ApplicationHelper
def link_to_add_fields(name, f, type)
・フォームのあるhtmlに
= link_to_add_fields “クラス”, f, :カラム
・javascriptで動かす