LoginSignup
13
11

More than 3 years have passed since last update.

【Ruby on Rails】フォームオブジェクトを使って検索キーワードをcontrollerに送る

Posted at

想定対象者

  • Ruby on Railsで検索フォームを独自で作りたい
  • ransackを使いたくない
  • Google Books APIを使ったポートフォリオを作りたい(本記事ではあんまり関係ないけど)

(個人的に)実現したいこと

Google Books APIでは以下URLにキーワードを入れるだけで検索結果を返してくれるという仕様があります。
https://www.googleapis.com/books/v1/volumes?q=(ここにキーワード)

これを使えば、最終的に以下のようなViewの実装が思い浮かびます。
(ただし、この解説は別記事で予定)

books_controller.rb
@books = 処理(keyword)
>> [book1, book2, book3, ....]
search.html.slim
= @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 が最高すぎるんだよな。

用法としては以下の通り。

  1. app/forms/を作り、スネークケース.rbを置く
  2. class キャメルケースでクラスを定義する
  3. そのクラスにAcitveModelのモジュールをincludeする

参考: Railsガイドすごい!!!笑
Active Model の基礎

実装

具体的に本記事のやりたいことに当てはめると、以下のコードになります。

app/forms/search_books_form.rb
class SearchBooksForm
  include ActiveModel::Model
  include ActiveModel::Attributes

  attribute :keyword, :string
end
  • include ActiveModel::Attributesをしたことでattributeメソッドを使えます。
  • attribute :keywordと書けば、@search_form.keywordを使えます。
app/views/books/search.html.slim
= 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 '検索する'
app/controllers/books_controller.rb
  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でコード書いてるときに日本語部分の赤下線部破線を消す方法
  • フォームオブジェクトの説明ってこれで合ってるでしょうか
13
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
11