想定対象者
- Ruby on Railsで検索フォームを独自で作りたい
- ransackを使いたくない
- Google Books APIを使ったポートフォリオを作りたい(本記事ではあんまり関係ないけど)
(個人的に)実現したいこと
Google Books APIでは以下URLにキーワードを入れるだけで検索結果を返してくれるという仕様があります。
https://www.googleapis.com/books/v1/volumes?q=(ここにキーワード)
これを使えば、最終的に以下のようなViewの実装が思い浮かびます。
(ただし、この解説は別記事で予定)
@books = 処理(keyword)
>> [book1, book2, book3, ....]
= @books.each do |book|
= image_tag book.image
= book.titile
= book.author
= (略)
検索フォームを作るgemとしてransackという有名なgemがあります。
ただ、アプリのDB内で検索を行う目的で使われるもののようです。
本記事では、実際に検索を行うロジックはGoogle Books APIにキーワードを送るだけなので、ransackを使う必要がないことになります。
※まともにransackを使った経験があるわけではありません。
上記の実装をするには、まずは検索キーワードをcontrollerに持ってくる必要があります。
その際にはフォームオブジェクトを使うのが良いです。
フォームオブジェクトとActiveModel
まず、フォームオブジェクト is 何
参考:
form objectを使ってみよう
フォームオブジェクトでバリデーション 初心者→中級者へのSTEP2/25
(他にもフォームオブジェクトで検索するとたくさん出てきます)
本記事に当てはめれば、
- form_withで検索キーワードだけを
books#search
に送る - ActiveModelをincludeしたクラスを作る
ということになります。
ActiveModel is 何
誤解を恐れずに言うと、ActiveRecordのDBと連携しない版
ActiveRecordはDBへの連携以外でも、validateだったり、attributeだったり、便利な機能があると思います。
DBへの連携は必要ないが、Viewに対するこれらの機能は使いたい、というケースの場合にはActiveModelを使うべき、ということになります。
検索キーワードをcontrollerに送りたいだけでDBとは連携させない、本記事のケースのような場合には適切です。
参考:
【ruby】ActiveModelを使ってDBと関係ないFormを作成する【Rails】
ActiveModel::Attributes が最高すぎるんだよな。
用法としては以下の通り。
- app/forms/を作り、スネークケース.rbを置く
- class キャメルケースでクラスを定義する
- そのクラスにAcitveModelのモジュールをincludeする
参考: Railsガイドすごい!!!笑
Active Model の基礎
実装
具体的に本記事のやりたいことに当てはめると、以下のコードになります。
class SearchBooksForm
include ActiveModel::Model
include ActiveModel::Attributes
attribute :keyword, :string
end
-
include ActiveModel::Attributes
をしたことでattributeメソッドを使えます。 -
attribute :keyword
と書けば、@search_form.keyword
を使えます。
= form_with model: @search_form, url: search_books_path, local: true, scope: q, method: :get do |f|
.form-group
= f.label :keyword, 'キーワード'
= f.text_field :keyword, class: 'form-control', value: @search_form.keyword
= f.submit '検索する'
def search
@search_form = SearchBooksForm.new(search_books_params)
# @search_form.keywordに検索キーワードが渡ったので、以下色々なことしちゃいましょう
end
private
def search_books_params
params.fetch(:q, keyword: '').permit(:keyword)
end
説明する前に力尽きたこと
- 検索結果というリソースはURLとして持つべきという話
- なぜGETメソッド使うのか
- scope: :q is 何
- fetch is 何
- 「色々なことしちゃいましょう」の「色々なこと」(本当なら検索して結果をまとめるロジックを「色々なこと」に書きます)
参考:
【Ruby on Rails】require と permit の使い方がよく分からない
あとでこの記事を修正して書くモチベが生まれるかもしれませんし、生まれないかもしれません。
教えてほしいこと
- markdownでコード書いてるときに日本語部分の赤下線部破線を消す方法
- フォームオブジェクトの説明ってこれで合ってるでしょうか