#はじめに
checkbox
で1つ以上選択必須の入力フォームを作っていきます。
今回は、チームを新規作成する際に活動曜日を最低1つ以上、かつ複数選択可の入力フォームを作っていきます。
#曜日カラムを作成する
Team
モデルは既に作成してある前提で進めていきます。
私は曜日ごとのカラムをboolean型
で作成しました。
$ rails g migration AddWeeklyToTeams
下記のように記述します。
class AddWeeklyToTeams < ActiveRecord::Migration[6.1]
def change
add_column :teams, :activity_monday, :boolean
add_column :teams, :activity_tuesday, :boolean
add_column :teams, :activity_wednesday, :boolean
add_column :teams, :activity_thursday, :boolean
add_column :teams, :activity_friday, :boolean
add_column :teams, :activity_saturday, :boolean
add_column :teams, :activity_sunday, :boolean
end
end
マイグレーションを行います。
$ rails db:migrate
#Viewファイルを記述する
まず活動曜日のカラムを配列で取り出せるようにweekly_columns
を定義します。
def weekly_columns
['activity_monday', 'activity_tuesday', 'activity_wednesday',\
'activity_thursday', 'activity_friday', 'activity_saturday', 'activity_sunday']
end
次にViewファイルを書いていきます。
<%= form_with(model:@team,local:true) do |f| %>
<p>活動曜日</p>
<span class = "checkbox-inline">
<% weekly_columns.each_with_index do |day,i| %>
<%= f.check_box day.to_sym , {} ,"true", "false" %>
<%= f.label day.to_sym , ["月","火","水","木","金","土","日"][i] %>
<% end %>
</span>
<% end %>
ここでは、each_with_index
を使って取り出した要素に番号を付けています。
f.label
では取り出したカラム名に対応した曜日を表示し、
to_sym
では取り出したカラム名をシンボルにしています。
スタイルを少し整えて次のようになります。
しかしこのままでは、曜日を一つも選択していない場合でも登録ができてしまいます。
#独自バリデーションを作成する
独自バリデーションを作って、全てのcheckbox
がfalse
の場合にはエラーを返します。
class Team < ApplicationRecord
# 曜日カラムをtrueとfalseしか受け取らないようにする
with_options inclusion: {in: [true, false]} do
validates :activity_monday
validates :activity_tuesday
validates :activity_wednesday
validates :activity_thursday
validates :activity_friday
validates :activity_saturday
validates :activity_sunday
end
#ここからが独自バリデーション
validate :weekly_checked
#曜日が1つ以上選択されていること
def weekly_checked
if activity_monday == false && activity_tuesday == false && activity_wednesday == false \
&& activity_thursday == false && activity_friday == false && activity_saturday == false && activity_sunday == false
errors.add(:weekly,"を1つ以上選択してください")
end
end
end
バリデーションに引っかかった際にはcheckbox
の下に
エラーメッセージを表示するようにします。
<%= form_with(model:@team,local:true) do |f| %>
<p>活動曜日</p>
<span class = "checkbox-inline">
<% weekly_columns.each_with_index do |day,i| %>
<%= f.check_box day.to_sym , {} ,"true", "false" %>
<%= f.label day.to_sym , ["月","火","水","木","金","土","日"][i] %>
<% end %>
</span>
<%# 追記 %>
<%= render 'shared/form_error_messages', object: f.object, attribute: :weekly %>
<% end %>
<% if object.errors.any? %>
<div class="form-alert-danger">
<ul>
<% object.errors.full_messages_for(attribute).each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
エラーメッセージを日本語化します。
ja:
activerecord:
attributes:
team:
weekly: 活動曜日
checkbox
を一つも選択せずに登録をしようとすると、次のようなエラー文が表示されます。
#チームプロフィールで活動曜日を表示する
各曜日カラムの中でtrue
の曜日だけ表示していきます。
<p>活動曜日</p>
<% weekly_columns.each_with_index do |day,i| %>
<% if @team[day] == true %>
<a><%= ["月","火","水","木","金","土","日"][i] %></a>
<% end %>
<% end %>
#最後に
曜日を1つ以上選択必須かつ、複数選択できる入力フォームを実装するために
色々と調べましたがドンピシャな記事を見つけることができませんでした...。
しかし、DB設計からかなり苦戦しながらも、なんとか実装することができました。
同じ悩みを抱えている方の参考になれば幸いです!