Posted at

Ruby on Railsとfullcalendar pluginでGoogleカレンダークローンを作る(2)

More than 5 years have passed since last update.

前回、カレンダーの枠まで表示できるようにしたので、

今回はイベントを登録して表示できるようにしてみる。


イベントを表示させる

scaffoldでeventを生成する。

カラムはfullcalendarのevent objectに合わせる。

bundle exec rails g scaffold event title start:datetime end:datetime color allDay:boolean

bundle exec rake db:migrate

localhost:3000/events/newからeventをDBに登録できるようになるので、

適当に登録しておく。

登録したeventはlocalhost:3000/eventsで参照できる。

また、localhost:3000/events.jsonとすると登録されたeventをjson形式で取得できる。

calendar.jsを以下のように書き換える。

eventsオプションで上記のeventをjson形式で取得するURLを指定することで、eventをカレンダー上に表示できるようになる。


calendar.js

$(document).ready(function() {

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


イベントをカレンダーから登録する

まずはカレンダーを選択できるようにする。

そのためにはselectableオプションをtrueにして、selectオプションにコールバック関数を登録する。

引数は選択の開始日と終了日(1日だけ選択した場合には開始日と同じ日になる)、終日かのフラグ(月表示の場合はtrue)。


calendar.js

$(document).ready(function() {

$('#calendar').fullCalendar({
events: '/events.json',
selectable: true,
selectHelper: true,
select: function(start, end, allDay) {
console.log('start:' + start);
console.log('end:' + end);
console.log('allDay:' + allDay);
alert('selected');
}
});
});

このコールバック関数内で、rails側にリクエストを投げてeventを登録する。

/eventsにPOSTでデータを投げればよいので、以下のようにしてみた。


  • promptでtitleを受け取り、dataを作ってajaxで/eventsに投げる。

  • 成功したら、refetchEventsを呼んでデータの再取得・再描画を行う。

  • 最後にunselectを呼んで、選択を解除する。


calendar.js

$(document).ready(function() {

var select = function(start, end, allDay) {
var title = window.prompt("title");
var data = {event: {title: title,
start: start,
end: end,
allDay: allDay}};
$.ajax({
type: "POST",
url: "/events",
data: data,
success: function() {
calendar.fullCalendar('refetchEvents');
}
});
calendar.fullCalendar('unselect');
};

var calendar = $('#calendar').fullCalendar({
events: '/events.json',
selectable: true,
selectHelper: true,
ignoreTimezone: false,
select: select
});
});


個人的に2カ所でハマった。

1つ目はデータの受け渡しのところで、一度データを変数に入れないとrails側で認識できなかった。

2つ目は日付の扱いで、js側からはJSTで日付を送っているが、rails側ではUTCに変換してDBに保存するため、タイムゾーンを考慮する必要があった。

これについては、ignoreTimezoneオプションをfalseにすることで解決できた。