Posted at

Rails で簡単にカレンダーを扱える simple_calendar で週表示カレンダーのフォーム作成を試す

More than 1 year has passed since last update.


はじめに

Rails でカレンダーを簡単に取り扱えそうな simple_calendar という gem の存在を知りました。

そこで、週表示のカレンダーで、それぞれの日に予定を入れるフォームを作るとどんな感じになるか、サンプルを作りながら検証しました。

view は読みやすくするために haml も導入して試そうと思います。


環境の前提


  • Rails 5.1.6

  • ruby 2.4.3


目標

下記のような、日毎に入力フォームがある週表示カレンダーの作成を目指します。


手順


1. 初期設定


rails アプリケーション新規作成

以下コマンドを実行します。

$ rails new calendar-sample

$ cd calendar-sample


Gem インストール

今回利用する simple_calendar, haml-rails をインストールします。


Gemfile

# 追記

gem 'simple_calendar', '~> 2.0'
gem 'haml-rails'

$ bundle


simple_calendar の view テンプレートを生成

あとから simple_calendar のデザインを修正できるように、テンプレートを生成します。

$ rails g simple_calendar:views


haml に変換

haml-rails のコマンドで haml に変換します。

$ rake haml:erb2haml


サンプル Model作成

表示確認用の Meeting モデルを scaffold で作成します。

$ rails g scaffold Meeting name start_time:date content:string


simple_calendar のカレンダー表示設定

週表示でカレンダーを表示できるよう、simple_calendar を設定します。


app/views/meetings/index.html.haml

-# 追記

= week_calendar do |date|
= date


表示確認

Migrateしてサーバを起動します。

$ rails db:migrate

$ rails s

http://localhost:3000/meetings にアクセスし、週表示カレンダーが表示されていることを確認します。


2. カレンダーのフォーム作成


route 登録

一括でデータ登録用のメソッドを routes に定義に定義します。


config/routes.rb

Rails.application.routes.draw do

resources :meetings do
collection do
post :update_week
end
end
end


view 実装

日毎に content が入力できるようなフォームを実装します。


app/views/meetings/index.html.haml

-# 以下に書き換え

%h1 Week Meetings

= form_for :meeting, url: update_week_meetings_path, html: { method: :post } do
= week_calendar do |date|
= date
- meeting = @meetings.find_or_initialize_by(start_time: date)
- if meeting.id.nil?
%p
= hidden_field_tag "meeting[#{date}][start_time]", date
%p
= text_field_tag "meeting[#{date}][content]"
- else
= fields_for "meeting[]", meeting do |meeting_fields|
%p
= meeting_fields.hidden_field :start_time
%p
= meeting_fields.text_field :content
= submit_tag


メソッドに find_or_initialize_by を使うことで、レコードの新規作成・編集どちらにも対応できるようにしています。

また、 meeting.id の有無で処理を分岐させていますが、これはクエリパラメータの形を統一するためです。

既存データはidをキーとしたハッシュで格納されるのに対し、新規データはidがないのでハッシュの配列で格納されます。

idがある場合

 "meeting"=>

{"1"=>{"start_time"=>"2018-07-02", "content"=>"A"},
"2"=>{"start_time"=>"2018-07-03", "content"=>"B"}}

idがない場合

 "meeting"=>

[{"start_time"=>"2018-07-02", "content"=>""},
{"start_time"=>"2018-07-03", "content"=>""}]

そのため、配列が入ったクエリパラメータをPOSTしようとすると下記エラーが生じるため、ハッシュを使う形に統一できるようにしています。

Rack::QueryParser::ParameterTypeError (expected Hash (got Array) for param `meeting'):


参考URL


controller 設定

view で入力された複数日のデータを一括で登録・更新するためのメソッドを実装します。


app/controllers/meetings_controller.rb

  # 追記

def update_week
week_meetings_params.keys.each do |key|
@meeting = Meeting.find_or_initialize_by(start_time: week_meetings_params[key][:start_time].to_date)
@meeting.update_attributes(week_meetings_params[key])
end
redirect_to meetings_path
end

# 中略...

private
# 追記
def week_meetings_params
params.require(:meeting).permit!
end


http://localhost:3000/meetings にアクセスし、週ごとのフォームが更新できることを確認します。


終わりに

突貫で作成したサンプルなので粗い部分もあるかと思いますが、simple_calendar を使った週表示のフォームを試すことが出来ました。カレンダー部分の処理をシンプルに取り扱えて便利だなと思いました。


参考URL