パターン
- Ransackを使う
- コントローラーに書く
- Concernに書く
- Formオブジェクトを使う
Ransackを使う
Ransack使うとソートも楽に書けそうだけど、
追々カスタマイズが面倒そうなのもあり最初から自分で書くことが多い。
あまり使ったこと無いので、ケースによっては触ってみたい。
コントローラーに書く
comments = Comment.where(post_id: params[:post_id]) if params[:post_id].present?
こんな感じでコントローラーに直接where文を書くケース。
何も考えずに書くとこうなることが多いと思う。
条件式が増えてくると複雑度上がってrubocopに怒られる。
Concernに書く
module Comments
module SearchModule
extend ActiveSupport::Concern
def self.do_search(params)
comments = Comment.all
search_by_post_id(comments, params[:post_id]) if params[:post_id].present?
end
def self.search_by_post_id(comments, post_id)
comments.where(post_id: params[:post_id])
end
end
end
Comments::SearchModule.do_search(params)
検索用のConcernモジュールに切り分ける方法。FatControllerはこれで解消できるので良さげ。
ただConcern特有のお作法があるので、自由に書きづらく、単純なクラスが使いたくなった。
Formオブジェクトを使う
class CommentSearchForm < SearchForm
attribute :post_id, Types::Maybe::Coercible::Integer
def do_search
comments = Comment.all
search_by_post_id(comments, post_id.value_or) if post_id.value_or.present?
end
private
def search_by_post_id(comments, post_id)
comments.where(post_id: post_id)
end
end
Dry::Types.load_extensions(:maybe)
module Types
include Dry::Types.module
end
class SearchForm < Dry::Struct
end
CommentSearchForm.new(params.to_hash.symbolize_keys).do_search
モデルに紐付かないパラメータを処理する時にはVirtusが便利で良く使われているそう。
ただ公式リポジトリをみると作者が後継ライブラリであるdry-rb
を推奨していたので、dry-rbを元に実装した。
https://github.com/solnic/virtus
厳密には型指定のみなので以下の3つ。
dry-validation
でバリデーションも出来るようなので、後々使ってみたい。
gem 'dry-monads'
gem 'dry-struct'
gem 'dry-types'
普通にgemをインストールすると一番古い0.5系になるので、最新の使い方とは違うので注意。
Formオブジェクトを使ったことで、次のようなメリットがある気がする。
まだ余り使いこなせてないので詳しい方の意見聞きたい。
- フォーム関連の処理が書かれていることがひと目でわかる
- FatController対策になる
- シンプルなクラスでテスト書きやすい