Help us understand the problem. What is going on with this article?

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

目標

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

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3232323033302f33393063663362642d353836372d653762392d383265372d3139333462633330653130332e706e67.png

手順

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 にアクセスし、週表示カレンダーが表示されていることを確認します。

Screen Shot 2018-06-30 at 11.45.41.png

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 にアクセスし、週ごとのフォームが更新できることを確認します。

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3232323033302f33393063663362642d353836372d653762392d383265372d3139333462633330653130332e706e67.png

終わりに

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

参考URL

sonicgarden
「お客様に無駄遣いをさせない受託開発」と「習慣を変えるソフトウェアのサービス」に取り組んでいるソフトウェア企業
http://www.sonicgarden.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした