Ruby on Railsにて、検索フォームを使用した際に、受け渡す値にvalidationを加えたい時、ありますよね。
form_forやform_tagを使用した際のクエリ,パラメータにvalidationを加える方法を書きます。
Formオブジェクトというデザインパターンのひとつです。
RailsTutorialを絶賛挑戦中や、終わってから少し応用的なことをしている人は同じようなことで困っているかと思います。
参考にになれば幸いです!
おおまかな流れ
- modelによるvalidationを利用するため、フォーム用のクラスを作成する。
- クラスにvalidationを記述しておく
- コントローラ内で作ったクラスをインスタンス化させる時に引数として渡してvalidationを適用させる
といった流れですね。
内容
主に検索フォームを使用した例はこちら
RailsTutorial7章より
<%= form_for(@user) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.email_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>
このコードでは、以下のコントローラで定めたUserのモデルオブジェクトを使用したformを作成しています。
つまり、@userに対して働きかけが行うようにしているといったものです。
@userはmodelであるUserからインスタンス化したものです。
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
end
ここで、validationがかかるタイミングはmodelを作成しようとした時です。
上記のmodelのUserをみてみましょう。
class User < ActiveRecord::Base
validates :name, presence: true
end
こちらのUserは ActiveRecordを継承して作成しています。
ここがポイントです。
ActiveRecordを継承して作成したmodelオブジェクトは、簡単に言えばDBとやりとりを行うmodelとなります。
modelでは、createやnewを行うタイミングでvalidationが適用されます。
ここでは,validates :name, presence: true
の部分ですね。
name属性(変数)は、空はだめですよ、といっています。
さて、modelオブジェクトを使えばvalidationをさせる仕組みは揃っているということです。
こちらを利用します。
ただし、今回のparams[:keyword]
のような一時的な値の受け渡しにおいていちいちDBに保存していると時間がかかってダメです。
そこで、一時的に格納するオブジェクトを作成することで解決させます。
以下のようなclassを新たに
app/models/の中に作成します。
クラスの名前、attr_accessorの変数名は各自で設定してください。
クラスにおける変数としてattr_accessor
で定義します。
class SearchForm
include ActiveModel::Model
attr_accessor :keyword
validates :keyword, presence: true
end
validates :keyword, presence: true
の部分はvalidates :keyword, presence: true, length: { maximum: 10 }
のようにvalidationを追加してもよいでしょう。
ここでポイントは2点です。
- class に < ActiveRecordがないこと
include ActiveModel::Model
ActiveRecordを継承しないのは、DBとやりとりをしないclassであるととらえておいて問題なさそうです。
include ActiveModel::Model
についても、このように記述すると思っておきましょう。
詳しくは追加でググりましょう。
さて、これでmodelを用意することができました。
あとはこちらのクラスを使ってインスタンス化を行えば自動的にvalidationがされるはずです。
コントローラ内にてこんな感じになると思います。
SearchFormのクラスは作ってあるため、コントローラで使えます。
word = SearchForm.new(keyword: params[:search_keyword])
newしてあげる時にparamsで値をkeywordに入れてあげましょう。
この時にvalidationが行われます。
ここで一度、rails consoleを用いてvalidationに応じていろいろと値を入れてみて試すとvalidationが行われているか確かめることができます。
>word = SerchForm.new ( keyword: "aaaaaaa")
>word.valid?
長さのvalidationをかけているならこんな感じですね。
>word = SerchForm.new ( keyword: "")
空白をチェックするならこんな感じ。
と、これでvalidationが適用されることになったので、あとはインスタンス変数の(この場合は)wordを使いましょう。
params[:keyword]としていたところをwordを使ってあげるとOKです。
参考記事
form objectを使ってみよう - メドピア開発者ブログ