Closed4

Railsで検索ツールを実装する際の検討・実装の流れ

なかじなかじ

検索機能にあたっての調査

今回の使用を検討

  • タグについてはタグをタップすると検索できるように実装済み

1. Active Modelでclass SearchArticlesFormを作成して実装⭕️

  • モデルでクエリ処理をscopeメソッドを作成する
  • カリキュラムで実装経験あり。ActiveModel::ModelActiveModel::Attributesをインクルードしたクラスを作成し、検索のためのメソッドを作成
  • コントローラでSearchArticlesForm用のインスタンスを作成して検索
  • 中間テスト・応用ではこちらを使用。ひとまずgem使わない形で実装する。

2. gem ransackを使用して実装

今回は使わないけど参考(全文検索系)

  • それほど検索機能を重視していないので今回は選択肢から外す
  • ただ RDBMSでSQLの検索行うよりも、自由度高く検索できそうで面白そう。AI使った検索とかできるっぽい。

3. Elasticsearch

  • バトランオフ会でかずちゃんさんが使ったと話してた
  • 大量データ、スピード検索に良いらしい。

RDBMS => データベース => テーブル => 列/行
Elasticsearch => クラスター => インデックス => シャード => キーバリューペアから構成されたドキュメント
引用元:Elasticsearchのインデックスとは? | Elastic Blog

使用するgem

4. Solr

5. Algolia

なかじなかじ

FormObjectの導入

FormObjectとは何か?

  • モデルとフォームの責務を切り分けることができる
  • Railsでは基本的にフォームはモデルに依存している(ユーザー新規登録ででform_withを使う際、model: @userと指定していることからも分かる)
  • ただ複数のモデルに依存するフォーム(検索など)やモデルが存在しないフォーム(ログインなど)もあり、その際使えるのがFormObject
  • 【Rails】FormObject を使って、複数のテーブル情報を同時保存 #Ruby - Qiita

導入の方法

  • app配下にformディレクトリを作成して、そこに必要なフォームを作成
$ mkdir app/forms      
$ touch app/forms/search_posts_form.rb
  • ファイル名はスネークケース、クラス名はキャメルケース(Railsだとこの辺りrails gすると自動で生成されるのであまり意識したことがなかった)
  • ActiveModel::ModelActiveModel::Attributesをインクルードする
class SearchPostsForm
include ActiveModel::Model
include ActiveModel::Attributes

end

参考資料

なかじなかじ

検索用のフォームビューを作成

ルーティングの設定

config/routes.rb
  resources :posts do
    collection do
      get :search
    end
  end
  • search_posts_pathが使えるようになる

フォームの作成

app/views/posts/_search_post_form.html.erb
<%= form_with model: search_form, url: search_posts_path, scope: :q, method: :get  do |f|%>
    <%= f.search_field :address_or_body, 
        id: 'search_field_of_post',    
        class: 'input input-borderd input-accent form-control mb-6 w-full md:w-1/2 mx-auto',
        placeholder: '場所・投稿内容' %>
    <%= f.submit '検索', class: 'btn btn-primary w-full my-6' %>
<% end %>
  • method: :get:form_withのアクションを指定。何もつけないとデフォルトはPostメソッドになるため、ActionController::RoutingError (No route matches [POST] "/posts/search"):とエラーが出る。
  • form_with | Railsドキュメント
なかじなかじ

enumで選択式の検索を実装する際の注意点

viewファイル

app/views/posts/_search_post_form.html.erb
    <%= f.select :genre_select, Post.enum_options_for_select(:genre), { include_blank: "未選択" },
        id: 'search_field_of_genre',
        class: 'bg-card-body bg-base-100 rounded-3xl border border-accent py-2 px-3 mb-6 w-full md:w-1/2 mx-auto' %>

フォームオブジェクトの設定

app/forms/search_posts_form.rb
class SearchPostsForm
  include ActiveModel::Model
  include ActiveModel::Attributes

  # フォームと関連付けするための属性。ActiveModel::Attributesがあるから設定できる。
  attribute :address_or_body, :string
  attribute :genre_select, :string
#...
end
  • attribute:stringにしておく必要がある
  • 最初enum使っているのでintegerにしたら何で検索してもenumで0にしてある和食しか出てこなかった
このスクラップは2ヶ月前にクローズされました