ransackで親子関係テーブルの検索 [Ruby on Rails]
1つのフォームで「親子関係」がある複数のテーブルを検索する方法です。
モデル(テーブル構成)
例として「掲示板システム」で「questions」(質問テーブル)、「answers」(回答テーブル)をransackで扱う仕様とします。

questions - 質問テーブル
項目名 | 型 | 備考 |
---|---|---|
id | integer | |
title | string | タイトル |
answers - 回答テーブル
項目名 | 型 | 備考 |
---|---|---|
id | integer | |
question_id | integer | questionsテーブルのid |
name | string | 名前 |
url | string | URL |
body | string | 本文 |
コントローラー側
def index @q = Question.all.ransack(params[:q]) @questions = @q.result end
@qは検索パラメータ、@questionsは検索結果です。
ビュー側
SlimとBootstrap4を使用しています。※erbの方は後述するHTMLを参考。
= search_form_for @q, class: 'mb-5' do |f| .form-group.row = f.label :title_cont, 'タイトル', class: 'col-sm-2 col-form-label' .col-sm-10 = f.search_field :title_cont, class: 'form-control' .form-group.row = f.label :answers_body_cont, '本文', class: 'col-sm-2 col-form-label' .col-sm-10 = f.search_field :answers_body_cont, class: 'form-control' .form-group = f.submit class: 'btn btn-outline-primary'
[出力されるHTML]
<form class="mb-5" id="question_search" action="/questions" accept-charset="UTF-8" method="get"> <div class="form-group row"> <label class="col-sm-2 col-form-label" for="q_title_cont">タイトル</label> <div class="col-sm-10"> <input class="form-control" type="search" name="q[title_cont]" id="q_title_cont" /> </div> </div> <div class="form-group row"> <label class="col-sm-2 col-form-label" for="q_answers_body_cont">本文</label> <div class="col-sm-10"> <input class="form-control" type="search" name="q[answers_body_cont]" id="q_answers_body_cont" /> </div> </div> <div class="form-group"> <input type="submit" name="commit" value="検索" class="btn btn-outline-primary" data-disable-with="検索" /> </div> </form>
モデル側
[question.rb]
class Question < ApplicationRecord # 複数のAnswerを子に持つ has_many :answers # 検索対象のカラム ※デフォルトは全て def self.ransackable_attributes(auth_object = nil) %w[title] end end
[answer.rb]
class Answer < ApplicationRecord # Questionに属する belongs_to :question # 検索対象のカラム ※デフォルトは全て def self.ransackable_attributes(auth_object = nil) %w[body] end end
必ず、「ransackable_attributes」で検索対象のカラム(項目)を指定します。デフォルトだと全てのカラムが対象になり、不正に検索される可能性がありますのでご注意ください。
(おまけ)複数キーワードによるAND検索の実装
タイトル(title)を例にすると次のような変数になります。
通常検索(1つ) | title_cont |
---|---|
OR検索(複数) | title_cont_any |
AND検索(複数) | title_cont_all |
def index # スペース区切りを配列に変換して返す。 if params[:q].present? params[:q]['title_cont_all'] = params[:q]['title_cont_all'].split(/[\p{blank}\s]+/) end @q = Question.all.ransack(params[:q]) @questions = @q.result end
スポンサーリンク
関連記事
公開日:2019年10月19日 最終更新日:2020年08月26日
記事NO:02795
この記事を書いた人
![]() | 💻 ITスキル・経験 サーバー構築からWebアプリケーション開発。IoTをはじめとする電子工作、ロボット、人工知能やスマホ/OSアプリまで分野問わず経験。 画像処理/音声処理/アニメーション、3Dゲーム、会計ソフト、PDF作成/編集、逆アセンブラ、EXE/DLLファイルの書き換えなどのアプリを公開。詳しくは自己紹介へ |
プチモンテ代表、アーティスト名:プチモンテ | |
🎵 音楽制作 BGMは楽器(音源)さえあれば、何でも制作可能。歌モノは主にロック、バラード、ポップスを制作。歌詞は叙情詩、叙情的な楽曲が多い。楽曲制作は2023年12月中旬 ~ |
オリジナル曲を始めました✨
YouTubeで各楽曲を公開しています🌈
https://www.youtube.com/@petitmonte