#author("2020-09-14T05:01:26+00:00","default:src128","src128") #author("2021-07-04T06:28:07+00:00","default:src128","src128") &tag(Ransack); *目次 [#mbfa3f82] #contents *関連ページ [#f1dfe5d2] -[[./ransack_demo]] *参考情報 [#ufc216e0] -[[activerecord-hackery/ransack:https://github.com/activerecord-hackery/ransack]] // 公式サイト -[[#370 Ransack - RailsCasts:http://railscasts.com/episodes/370-ransack?language=ja&view=asciicast]] -[[Ruby - Ransackのススメ - Qiita [キータ]:http://qiita.com/nysalor/items/9a95d91f2b97a08b96b0]] *概要 [#t14acaff] -Railsで検索画面を作るための(?)gem。 -Kaminariと組み合わせ、カラムクリックでソートすることもできる。 *簡単な使い方 [#z3adda50] **インストール [#a39b267a] -Gemfileにransackを追加。 gem "ransack" **コントローラ [#n4975c64] -コントローラーのaction。例えばindexで検索する場合次のようになる。 #pre{{ def index @search = Item.ransack(params[:q]) @items = @search.result end }} ※searchじゃなくてransackメソッドのほうが推奨になったらしい(公式サイト) **ビュー [#x2d55501] -検索条件を指定するフォームの作成 #pre{{ <%= search_form_for @search do |f| %> <%= f.text_field :title_cont %> <%= f.submit '検索' %> <% end %> <% @items.each do |item| %> (省略) <% end %> }} **述語の指定 [#d80f182e] -ビューでは、フィールド名の後ろに特定のワードを追加して条件を指定する。 -例えばtitle_contならばtitleに指定した文字が含まれるもの、age_gtならば指定した年齢以上の年齢のように。 ***eq [#c326fc18] -指定条件に一致するもの ***lt [#vf08d8a0] -指定条件より小さいもの。age_ltは「age <」。 ***lteq [#j9365451] -指定条件以下のもの。age_lteqは「age <= 」。 ***gt [#e56fd4ba] -指定条件より大きいもの。age_gtは「age > 」。 ***gteq [#c0e6256b] -指定条件より大きいもの。age_gteqは「age >=」。 ***_i_ 大文字小文字を無視して検索 [#hc7bd689] -「_i_」を入れると大文字小文字を無視して検索する。例えば「title_i_cont」のように。 *複雑な使い方 [#sc45293f] **2つのフィールドのどちらかに含まれるものを検索 [#s2313ecb] -[[Basic Searching · activerecord-hackery/ransack Wiki:https://github.com/activerecord-hackery/ransack/wiki/Basic-Searching]]より。 -単に2つのフィールドのどちらかに含まれるものを検索したい場合「first_name_or_last_name_cont」のように接続できる。 #pre{{ >> User.ransack(first_name_or_last_name_cont: 'Rya').result.to_sql => SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE '%Rya%' OR "users"."last_name" LIKE '%Rya%') }} **ANDとORを組み合わせる(グルーピング) [#r4aaa642] -[[how to?: search with condition OR 'is null' · Issue #290 · activerecord-hackery/ransack:https://github.com/activerecord-hackery/ransack/issues/290]] -[[Ransackでグループ間OR検索が分からない件 - エンジニアリングにはほど遠い:http://j-ogawa.hatenadiary.jp/entry/2014/03/25/000334]]…最後の追記を確認すること。 -パラメータで指定する倍、「g」と「m」を使い、ハッシュを入れ子にする。 #pre{{ User.search( g: { '0' => { m: 'or', power_gteq: 100, magic_gteq: 30 }, '1' => { m: 'and', level_gteq: 20, hp_lteq: 30 } } ).result }} -@q.build_groupingや、grouping_fieldsも覚えておくと良い。[[Ransackで A and (B or C) - Qiita:https://qiita.com/acro5piano/items/9f792d58f0647892d612]] *ビュー [#s2e33ac9] **search_form_for [#oe9ebf24] -search_form_forの定義は次のようになっている #pre{{ def search_form_for(record, options = {}, &proc) }} -最も単純 <%= search_form_for(@search) do |f| %> -クラスとurlを指定 <%= search_form_for(@search, url: items_path, html: {class: 'form-inline'}) do |f| %> *Tips [#q479a17d] **or条件で検索 [#qd7229d9] -[[activerecord-hackery/ransack: Object-based searching.:https://github.com/activerecord-hackery/ransack#grouping-queries-by-or-instead-of-and]] **orderを手動で指定したい場合 [#n4cd42c5] -[[Sorting in the Controller · activerecord-hackery/ransack Wiki:https://github.com/activerecord-hackery/ransack/wiki/Sorting-in-the-Controller]]に方法が書いてある #pre{{ @search = Post.ransack(params[:q]) @search.sorts = 'name asc' if @search.sorts.empty? #一つの場合 @search.sorts = ['name asc', 'created_at desc'] if @search.sorts.empty? # 複数の場合 @posts = @search.result.paginate(page: params[:page], per_page: 20) }} -params[:q][:s]に無理やり突っ込む方法は古い。 **orderを手動で指定したい場合(古い方法) [#p7643075] -params[:q][:s]にORDER BYの値を渡してやる。 params[:q][:s] = "rating desc" -もしくはresult.orderでソート。 @search.result.order("rating desc") **カラムクリックしたときの初回のソートの向きを指定したい [#rd598170] -sort_linkのdefault_orderを指定する。 <%= sort_link(@q, :name, 'Last Name', default_order: :desc) %> **カラムクリックしたとき、セカンドキーを指定したい(2番目以降は固定) [#g76343ea] -カラムのシンボルの後に、ソートに使う配列を指定する。以下の場合:last_nameと'first_name asc'でソートすることになる。 <%= sort_link(@q, :last_name, [:last_name, 'first_name asc'], 'Last Name') %> -カラムをクリックすると、「last_name asc」「last_name desc」のあと「first_name asc」が組み合わさってソートされる。 -first_nameの方向は入れ替わらないことに注意。 **カラムクリックしたとき、セカンドキーを指定したい(2番目以降もトグル) [#yc3d7103] -ソート配列はシンボルにして、default_orderで初期ソート方向を指定する。 #pre{{ <%= sort_link(@q, :last_name, %i(last_name first_name), default_order: { last_name: 'asc', first_name: 'desc' }) %> }} **テーブルカラムと対応しない列で並べ替える場合 [#z755b783] -上の応用となる。sort_orderにリストで選択された"ソート順"が入っているとする。そのソート順からORDER BYの文字列を作ってやりセットする。 params[:q][:s] = build_sql(params[:sort_order]) -view側で、params[:sort_order]を初期値としてセットしてやれば条件も引き回せる。 **検索条件の引き回し [#qc51926a] -検索フォームとページングのナビゲーションを組み合わせて使う場合、検索ボタンを押して検索したパラメータが、ページングのナビゲーションに追加されて検索条件が引き回されることになる。 -検索条件を変えたら、いったん検索しないといけない。 **検索パラメータの書き換え [#p95f71b3] -検索対象のカラムに直接該当しない値を画面から渡したい場合。 -ビュー側でf.selectを使うとransackのモデルにカラムが存在するかどうかのチェックが働く。select_tagのようにtagを使う。 #pre{{ <%= select_tag("q[complex_cond]", options_for_select()..) %> }} -コントローラーがわでparams[:q]のチェックを行い、ransackが認識可能なパラメータに置き換える if complex_cond == '1' @search.title_eq ='あああ' end