🍋

Rails カレンダー機能(simple_calendar)

2023/06/14に公開

はじめに

ポートフォリオ作成中のプログラミング初学者です🔰
今日は、simple_calendarという、gemを使い、ユーザーページにカレンダーを追加しました。

fullcalendarというgemもあるみたいですが、
⭐️が多く、実装がシンプルそうだったsimple_calendarを選びました。

フィットネス🏋🏻・食事🥗・ブログ📝投稿作成時に日時を指定して、
カレンダーに各絵文字を表示させました。絵文字をクリックすると、投稿詳細ページに飛びます。

投稿(フィットネス🏋(PostWorkout)・食事🥗(PostMeal)・ブログ📝(PostBlog)の)機能は実装済みです。

記述は省きますが、表示させたい投稿のdatetimeのカラム名をstart_timeにすることだけ気をつけてください!そうしないと、エラーが発生します!

t.datetime :start_time

実装

1. simple_calendarをインストール

  • Gemfileにsimple_calendarを追記します。
gem 'simple_calendar'
  • bundle installを忘れずに。
$ bundle install 

2. viewでカレンダーを表示させる

  • カレンダーを表示させたいviewファイルに以下コードを記述します。
  • これで月ごとのカレンダーが表示されます。(デザインはついていません。)
<%= month_calendar do |date| %>
 <%= date.day %>
<% end %>

3. カレンダーに任意のデータを入れる

  • コントローラーからデータを渡すことで任意のデータをカレンダー内に入れることができます。
<!-- カレンダー -->
<%= month_calendar events: @events do |date, events| %>
  <%= date.day %>
  <% events.each do |event| %>
    <div class="calendar__event">
      <% if event.is_a?(PostWorkout) %>
        <%= link_to '🏋️',post_workout_path(event) %>
      <% elsif event.is_a?(PostMeal) %>
        <%= link_to '🥗',post_meal_path(event) %>
      <% elsif event.is_a?(PostBlog) %>
      <%= link_to '📝',post_blog_path(event) %>
      <% end %>
    </div>
  <% end %>
<% end %>
is_a?メソッド
  • あるオブジェクトが特定のクラスのインスタンスであるかどうかを確認するために使用するメソッド。

  • 例えば、event.is_a?(PostWorkout)というコードは、eventオブジェクトがPostWorkoutクラスのインスタンスであるかどうかを判定します。もしeventがPostWorkoutのインスタンスであれば、このメソッドはtrueを返し、そうでなければfalseを返します。

@eventsの中身
    @post_workouts = @end_user.post_workouts
    @post_blogs = @end_user.post_blogs
    @post_meals = @end_user.post_meals
    @events = @post_workouts + @post_meals + @post_blogs
  • アソシエーションを結んでいることを前提としています。

4. デザインをカスタマイズする

  • 以下コマンドでsimple_calendarに関わるviewファイルを入手できます。
$ rails g simple_calendar:views

  • このファイルを修正したり、cssを追加したりすることでデザインをカスタマイズすることができます。

以上の流れでカレンダーを作成することができるはずです!

参考にさせていただいた記事🌱

https://tech-tech.blog/ruby/rails/simple_calendar/

https://qiita.com/isaatsu0131/items/ad1d0a6130fe4fd339d0

非同期化

  • 非同期化も実装しました。

1. 更新トリガーを remote :trueにする

simple_calendarフォルダ配下の_month_calendar.html.erbのカレンダーをめくるボタンを編集!

app/views/simple_calendar/_month_calendar.html.erb
<%= link_to t('simple_calendar.previous', default: '<'), calendar.url_for_previous_view, remote: true %>
:
<%= link_to t('simple_calendar.next', default: '>'), calendar.url_for_next_view, remote: true %>

2. 更新させたいviewを部分テンプレート化

カレンダー部分をテンプレート化します。

app/views/public/end_users/_calender.html.erb
<%= month_calendar events: events do |date, events| %>
  <%= date.day %>
  <% events.each do |event| %>
    <div>
      <% if event.is_a?(PostWorkout) %>
        <%= link_to '🏋️',post_workout_path(event) %>
      <% elsif event.is_a?(PostMeal) %>
        <%= link_to '🥗',post_meal_path(event) %>
      <% elsif event.is_a?(PostBlog) %>
      <%= link_to '📝',post_blog_path(event) %>
      <% end %>
    </div>
  <% end %>
<% end %>
ちなみにcontroller
public/end_user_controller
class Public::EndUsersController < ApplicationController
:
  def show
    @end_user = EndUser.find(params[:id])
    @post_workouts = @end_user.post_workouts
    @post_blogs = @end_user.post_blogs
    @post_meals = @end_user.post_meals
    @events = @post_workouts + @post_meals + @post_blogsend
end

部分テンプレートを呼び出しているviewはこのようになっています。
(public/end_users/show.html.erbで呼び出している部分テンプレート)
idをつけないと、JSファイルを呼び出せないです!

app/views/public/end_users/_profile.html.erb
  <div id="calendar">
    <%= render 'public/end_users/calendar', events: events %>
  </div>

3. アクション名.js.erbファイルを作り、更新処理を書く

showアクションでviewを呼び出しているのでshow.js.erbを作成します。

app/views/public/end_users/show.js.erb
$('#calendar').html("<%= j(render 'calendar', events: @events) %>");

これで月のカレンダーをめくるボタンを押した時に、カレンダー部分だけ更新できるようになります!

参考にさせていただいた記事🌱

https://qiita.com/wak10/items/a46433808b335aa8afc8

さいごに

カレンダー機能を入れることで、ユーザーが一目で日付ごとの投稿を把握できるようになりました。gemのおかげでとても簡単に実装できたので、ぜひやってみてください。

もし間違いなどあれば教えていただけますと幸いです!

今度やってみたいカスタマイズ⭐️
https://qiita.com/sssssatou/items/2e6606e3ddf9b246a0fb

Discussion