始めに
RailsTutorialを終えてから自分でアプリを作ろうと思い、カレンダーを使う必要があったのでググりました。
カレンダー機能はSimpleCalendarとかFullCalendarといったのが使われてるみたい。
FullCalendarはjQueryのプラグインでその知識も多少ないと使いづらいと思いますが、ドキュメント見る限り色々できそうなのでとりあえず手を出してみました。
今回はScaffoldを使って簡単なEventモデルを作って、とりあえずここまでできれば後は自由に使えそうかなーと思うところまでをメモっておきます。(途中躓いたところの対策も)
環境
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
内に次のコードを追加
//= require jquery
//= require moment
//= require fullcalendar
FullCalendarを正しく読み込むためにapplication.jsに二つの関数を作ります
$(function () {
function eventCalendar() {
return $('#calendar').fullCalendar({});
};
function clearCalendar() {
$('#calendar').html('');
};
});
一つ目の関数ではFullCalendarの設定を読み込み、二つ目の関数ではFullCalendarを削除します。
そして、RailsにはTurbolinksというツールを使ってページ遷移を高速にさせています。この機能がないと、Turbolinksを使っているときにカレンダーが複数回表示されることが起きてしまいます。
関数を追加したら、今度は呼び出すコードを(function clearCalendar(){...};
の下に)書きます
$(document).on('turbolinks:load', function () {
eventCalendar();
});
$(document).on('turbolinks:before-cache', clearCalendar);
application.cssを弄る
app/assets/stylesheets/application.css
内に*= require fullcalendar
を追加
...
*= 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
に以下のコードを追加
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
に次のコードを追加します。
$('#calendar').fullCalendar({
events: '/events.json'
});
最終的に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'
});
});
ちなみにルーティングは今こうなっています。
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"
属性を加えたら動作するようになりました。一応当時の対処法は残しておきます
仮に、こんな状態で予定があったとします。
ここからShowリンクをクリックして、ブラウザの戻るボタンを押すと、元のブラウザの画面に戻ります。このとき、TurbolinksによってjQueryが呼び出されないため、予定が表示されなくなってしまいます。
単純にapplication.js
の//= require turbolinks
を消してしまえば解決なのですが、今回はturbolinksを残したままバグを直します。
apprication.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月のようにしたり、レイアウト、時間の表示を設定できます。参考として自分がざっと設定してみたものを置いておきます。
$(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