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

RailsでFullCalendarを使って予定を表示するまで

始めに

RailsTutorialを終えてから自分でアプリを作ろうと思い、カレンダーを使う必要があったのでググりました。
カレンダー機能はSimpleCalendarとかFullCalendarといったのが使われてるみたい。
FullCalendarはjQueryのプラグインでその知識も多少ないと使いづらいと思いますが、ドキュメント見る限り色々できそうなのでとりあえず手を出してみました。

今回はScaffoldを使って簡単なEventモデルを作って、とりあえずここまでできれば後は自由に使えそうかなーと思うところまでをメモっておきます。(途中躓いたところの対策も)

練習なのでこんな感じの超簡単なアプリを作っていきます
image.png

環境

Ruby: 2.5.1
Rails: 2.5.1
OS: CentOS7

Gemの追加

Gemfileに使うjemを追加

gem 'jquery-rails', '4.3.3'
gem 'fullcalendar-rails'
gem 'momentjs-rails'

bundle installを実行

application.jsを弄る

app/assets/javascript/application.js内に次のコードを追加

app/assets/javascript/application.js
//= require jquery
//= require moment
//= require fullcalendar

FullCalendarを正しく読み込むためにapplication.jsに二つの関数を作ります

app/assets/javascript/application.js
$(function () {
    function eventCalendar() {
        return $('#calendar').fullCalendar({});
    };
    function clearCalendar() {
        $('#calendar').html('');
    };
});

一つ目の関数ではFullCalendarの設定を読み込み、二つ目の関数ではFullCalendarを削除します。
そして、RailsにはTurbolinksというツールを使ってページ遷移を高速にさせています。この機能がないと、Turbolinksを使っているときにカレンダーが複数回表示されることが起きてしまいます。

image.png
こんな感じ

関数を追加したら、今度は呼び出すコードを(function clearCalendar(){...};の下に)書きます

app/assets/javascript/application.js
$(document).on('turbolinks:load', function () {
    eventCalendar();
});
$(document).on('turbolinks:before-cache', clearCalendar);

application.cssを弄る

app/assets/stylesheets/application.css内に*= require fullcalendarを追加

app/assets/stylesheets/application.css
...
 *= require_tree .
 *= require_self
 *= require fullcalendar
 */

これで、あとはviewのerbファイルに<div id="calendar"></div>と書き込むだけでカレンダーが表示されます。(が、まだこれではイベント表示機能を付けた時に上手く表示されないときがあります。この後改修していきます。)
あとルーティングの設定も忘れずに!

イベントを表示する

Fullcalendarにイベントの情報を表示するには、JSONファイルを使ってあげます。
イベントにはタイトル、説明、開始日、終了日が必要です。今回はscaffoldで簡単に作ります。
rails generate scaffold Event title:string description:text start_date:datetime end_date:datetime
rails db:migrate

JSONを渡すために、Railsのjbuilderというものを使っていきます。scaffoldによってjson.jbuilderファイルが自動で作られています。
app\views\events\index.json.jbuilderに以下のコードを追加

app\views\events\index.json.jbuilder
json.array!(@events) do |event|
  json.extract! event, :id, :title, :description   
  json.start event.start_date   
  json.end event.end_date   
  json.url event_url(event, format: :html) 
end

こうすることで、{"id":"1", "title":"タイトル", "description":"説明", "start":"日付1", "end":"日付2", "url":"some_address"}みたいなjsonファイルが作られ?、カレンダーが読み込めるデータになります。
url項目があることで、カレンダーの予定にurlが埋め込まれ、クリックすると予定の詳細に飛ぶことができます。
FullCarendarで使えるデータについては公式ドキュメント参照

最後に、イベントを表示させるためにapp/assets/javascript/application.jsに次のコードを追加します。

app/assets/javascript/application.js
$('#calendar').fullCalendar({
    events: '/events.json'
});

最終的にapplication.jsはこうなってると思います。

app/assets/javascript/application.js
...

$(function () {
    function eventCalendar() {
        return $('#calendar').fullCalendar({});
    };
    function clearCalendar() {
        $('#calendar').html('');
    };
    $(document).on('turbolinks:load', function () {
    eventCalendar();
    });
    $(document).on('turbolinks:before-cache', clearCalendar);

    $('#calendar').fullCalendar({
    events: '/events.json'
    });
});

ちなみにルーティングは今こうなっています。

routes.rb
Rails.application.routes.draw do
  resources :events
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  root 'events#index'
end

これで終わり!...ではありません。この状態でも動くは動くのですが、バグが残っています。

バグの修正~完成!

3/26追記

以下で行う作業をしなくても、bodyタグにdata-turbolinks="false"属性を加えたら動作するようになりました。一応当時の対処法は残しておきます

仮に、こんな状態で予定があったとします。

image.png

ここからShowリンクをクリックして、ブラウザの戻るボタンを押すと、元のブラウザの画面に戻ります。このとき、TurbolinksによってjQueryが呼び出されないため、予定が表示されなくなってしまいます。
単純にapplication.js//= require turbolinksを消してしまえば解決なのですが、今回はturbolinksを残したままバグを直します。

apprication.js内を修正

app/assets/javascript/application.js
...

$(function () {
    // 画面遷移を検知
    $(document).on('turbolinks:load', function () {
        // lengthを呼び出すことで、#calendarが存在していた場合はtrueの処理がされ、無い場合はnillを返す
        if ($('#calendar').length) {
            function eventCalendar() {
                return $('#calendar').fullCalendar({
                });
            };
            function clearCalendar() {
                $('#calendar').html('');
            };

            $(document).on('turbolinks:load', function () {
                eventCalendar();
            });
            $(document).on('turbolinks:before-cache', clearCalendar);

            $('#calendar').fullCalendar({
                events: '/events.json'
            });
        }
    });
});

これで、ブラウザで戻るを利用しても予定が無事表示されるようになりました。

カレンダーのオプション

これまでに作ったカレンダーが、↑にあったような写真のカレンダーと若干表示が違っているはずです。

$('#calendar').fullCalendar({ });の{ }内にオプションを加えることで、カレンダーのタイトルをYYYY年MM月のようにしたり、レイアウト、時間の表示を設定できます。参考として自分がざっと設定してみたものを置いておきます。

application.js
$(function () {
    ...

            //events: '/events.json', 以下に追加
            $('#calendar').fullCalendar({
                events: '/events.json',
                //カレンダー上部を年月で表示させる
                titleFormat: 'YYYY年 M月',
                //曜日を日本語表示
                dayNamesShort: ['', '', '', '', '', '', ''],
                //ボタンのレイアウト
                header: {
                    left: '',
                    center: 'title',
                    right: 'today prev,next'
                },
                //終了時刻がないイベントの表示間隔
                defaultTimedEventDuration: '03:00:00',
                buttonText: {
                    prev: '',
                    next: '',
                    prevYear: '前年',
                    nextYear: '翌年',
                    today: '今日',
                    month: '',
                    week: '',
                    day: ''
                },
                //イベントの時間表示を24時間に
                timeFormat: "HH:mm",
                //イベントの色を変える
                eventColor: '#63ceef',
                //イベントの文字色を変える
                eventTextColor: '#000000',
            });
        }
    });
});

設定できる内容はたくさんあるので詳しくはドキュメントを参照してください。
また、Codeopen Fullcalendar とかでググったら簡単にカスタマイズの練習ができます!!

参考サイト

FullCalendarドキュメント
https://kaede.jp/2014/08/30175019.html
https://medium.com/@a01700666/fullcalendar-in-ruby-on-rails-f98816950039
jbuilderについて↓
https://qiita.com/ryouzi/items/06cb0d4aa7b6527b3645
jQueryの要素の存在の判別方法↓
http://black-flag.net/jquery/20150324-5622.html

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
ユーザーは見つかりませんでした