Rails: データベースに保存しないチェックボックス値のバリデーション
外観
目的
画面のチェックボックスがオンになっているかどうかを検証します。
チェックボックスの値はデータベースに保存しません。
Active Record バリデーション > 2.1 acceptance
これはWebアプリケーション特有のバリデーションであり、データベースに保存する必要はありません。これに対応するフィールドがなくても、単にヘルパーが仮想の属性を作成してくれます。
環境
Ruby 2.7.2
Rails 6.1.3.2
基礎
メールアドレスを持つAccountモデルを作成します。
新規作成画面に利用規約のチェックボックスを表示します。
メールアドレスと利用規約は必須入力にします。
rails new howto_validates_acceptance \
--skip-action-mailbox \
--skip-action-text \
--skip-active-storage \
--skip-action-cable \
--skip-javascript \
--skip-turbolinks \
--skip-jbuilder \
--skip-test \
&& cd howto_validates_acceptance && tmux
bin/rails g scaffold Account email
bin/rails db:migrate
# app/models/account.rb
class Account < ApplicationRecord
validates :email, presence: true
validates :terms_of_service, acceptance: true, on: :create
end
<!-- app/views/accounts/_form.html.erb -->
<% if account.new_record? %>
<div class="field">
<%= form.label :terms_of_service %>
<%= form.check_box :terms_of_service %>
</div>
<% end %>
# app/controllers/accounts_controller.rb
def account_params
params.require(:account).permit(:email, :terms_of_service)
end
応用
チェックボックスのデフォルト値にtrueを設定する。
チェックボックスの値の引き継ぐ。
チェックボックスとラベルを一列で表示する。
チェックボックスのデフォルト値にtrueを設定する。
<!-- app/views/accounts/_form.html.erb -->
<%= form.check_box :terms_of_service, { checked: true } %>
チェックボックスの値の引き継ぐ。
入力エラーとなった場合、前回の入力値を画面に表示する。
<!-- app/views/accounts/_form.html.erb -->
<%= form.check_box :terms_of_service, { checked: @terms_of_service } %>
# app/controllers/accounts_controller.rb
def new
@account = Account.new
@terms_of_service = false
end
def create
@account = Account.new(account_params)
if @account.save
redirect_to @account, notice: 'Account was successfully created.'
else
@terms_of_service = param_terms_of_service?
render :new
end
end
def param_terms_of_service?
ActiveRecord::Type::Boolean.new.cast(account_params[:terms_of_service])
end
チェックボックスとラベルを一列で表示する。
スキャフォールドのレイアウトはラベルの下にチェックボックスが表示されます。
これをチェックボックスの右にラベルを表示するように変更します。
<!-- app/views/accounts/_form.html.erb -->
<% if account.new_record? %>
<div class="field">
<%= form.label :terms_of_service do %>
<%= form.check_box :terms_of_service, { checked: @terms_of_service } %>
Terms of service.
<% end %>
</div>
<% end %>
// app/assets/stylesheets/scaffolds.scss
.field_with_errors > label > .field_with_errors {
display: inline; }
今回はconfig.action_view.field_error_procを用いずCSSを修正しました。また、どうせならCSSのhas疑似クラスでチェックボックスを子に持つ要素として指定したかったのですが、現時点でどのブラウザも未対応でした。
以上です。
この記事が気に入ったらサポートをしてみませんか?