[RUBY] Calendar implementation and conditional branching in Rails Gem simple calendar

Overview

I am currently studying at a programming school called DMM WEB CAMP. When creating the portfolio, I created an event table and displayed it on the calendar. I hope it will be useful for those who will create it.

Completion drawing

スクリーンショット 2020-06-25 19.05.35.png

Articles that I used as a reference

[Rails] Calendar display using Simple Calendar https://qiita.com/mikaku/items/0971442a7308dc669122

github https://github.com/excid3/simple_calendar

Advance preparation

Event table

スクリーンショット 2020-06-25 18.01.19.png

-Date and time when data_and_time starts ・ Date and time when meeting finish time ends

Event participation table

association

models/event.rb


class Event < ApplicationRecord
 has_many :event_participates, dependent: :destroy
end

models/event_participate.rb


class EventParticipate < ApplicationRecord
 belongs_to :event
end

gem install

gem 'simple_calendar', '~>2.0'
$ bundle install

View installation of Simple calendar

$ rails g simple_calendar:views

・ Three types of calendar templates can be created in views / simple_calendar.

Description in application.scss (CSS)

stylesheets/applecation.scss


*= require simple_calendar
*= require_tree .
*= require_self

start_time End_time definition

models/event.rb


class Event < ApplicationRecord
  has_many :event_participates, dependent: :destroy

  def start_time
    self.date_and_time
  end

  def end_time
    self.meetingfinishtime
  end
end

This gem requires the definition of start_time and end_time. (Especially start_time) It's okay if the column you're creating has that name from the beginning, but if it's a different column name, let's define it in the model. However, since it deals with date and time, I think the data type should probably be datetime. When I implemented it without defining it at first, I got an error.

In github, I used scaffold to create a column with the above name from the beginning.

Calendar display

My portfolio

views/events/index.html.erb


</div>
		<div class= 'calender'>
			<%= month_calendar events: @events do |date, event| %>
		  		<%= date %>

			 	<% event.each do |event| %>
			 	<br>
			 	<% if user_signed_in? %>
			 		<% if event.user_id == current_user.id %>
						<i class="fa fa-circle notification-circle" style="color: red;"></i>
					<% end %>
				<% end %>
				  	<% if event.event_participates.where(user_id: current_user).exists? %>
					    <span class="participate">
					      <%= link_to event.title,event_path(event) %>
					    </span>
					<% else %>
						 <span class="other">
					      <%= link_to event.title,event_path(event) %>
					    </span>
				  	<% end %>
				<% end %>
			<% end %>
		</div>

If you only want to display the calendar and the title of the event, you only need the following.

<div class= 'calender'>
			<%= month_calendar events: @events do |date, event| %>
		  		<%= date %>

			 	<% event.each do |event| %>
                  <%= event.title %>
                <% end %>
            <% end %>
</div>

controllers/events_controller.rb


def index
    @events = Event.all
end

Event.all defined in the controller is stored in @events and displayed in the calendar. <%= month_calendar events: @events If you change events: in this syntax, you will probably get an error, but I think it's okay to use any instance variable that stores the information.

Currently, I am using the month_calendar that I installed earlier, but since there are two other templates available, it seems that I can use from three types.

If I take the participate action, the background-color will be orange, If it is an event that is being hosted, I wanted to add a red circle icon, so make the following conditional branch I did it in the calendar.

  <% if event.user_id == current_user.id %>
     <i class="fa fa-circle notification-circle" style="color: red;"></i>
  <% end %>

If the user_id (that is, the event creator) in the event table is yourself, the font awesome icon will be displayed before the event title. I think anything here is fine as long as it is an inline element.

next


 <% if event.event_participates.where(user_id: current_user).exists? %>
      <span class="participate">
        <%= link_to event.title,event_path(event) %>
      </span>
<% else %>
      <span class="other">
        <%= link_to event.title,event_path(event) %>
      </span>
<% end %>

In the first line <% if event.event_participates.where (user_id: current_user) .exists?%> I am looking for whether I (current_user) exists among the users who participate in the event (participete). If you find it, class participate, otherwise class other, Even if the information to be displayed is the same, the class name can be different.

All you have to do is change the color with CSS, so please do whatever you like.

By the way, the view of month_calender is as follows.

views/simple_calendar/_month_calendar.html.erb


<div class="simple-calendar">
  <p class="carendar-title"><%= "#{Date.today.month}Monthly event schedule" %></p>

  <div class="calendar-heading" data-turbolinks="false">
    <!--%= link_to t('simple_calendar.previous', default: 'Previous'), calendar.url_for_previous_view %-->
    <!-- <span class="calendar-title"><%= t('date.month_names')[start_date.month] %> <%= start_date.year %></span> -->
    <!--%= link_to t('simple_calendar.next', default: 'Next'), calendar.url_for_next_view %-->
    <i class="fa fa-circle notification-circle" style="color: red;"><span>Hosted event</span></i>
    <span class="calendar-info">Participation plan</span>
  </div>

  <table class="table table-striped calendar-table">
    <thead>
      <tr>
        <% date_range.slice(0, 7).each do |day| %>
          <th><%= t('date.abbr_day_names')[day.wday] %></th>
        <% end %>
      </tr>
    </thead>

    <tbody>
      <% date_range.each_slice(7) do |week| %>
        <tr>
          <% week.each do |day| %>
            <%= content_tag :td, class: calendar.td_classes_for(day) do %>
              <% if defined?(Haml) && respond_to?(:block_is_haml?) && block_is_haml?(passed_block) %>
                <% capture_haml(day, sorted_events.fetch(day, []), &passed_block) %>
              <% else %>
                <% passed_block.call day, sorted_events.fetch(day, []) %>
              <% end %>
            <% end %>
          <% end %>
        </tr>
      <% end %>
    </tbody>
  </table>
</div>

I commented out the upper part in the specifications of my portfolio. A link to the next month or the previous month will appear in the comment out location. It seems that you can change it flexibly if it is a small part.

Summary

At first, I planned to implement it with full calendar, but I couldn't understand it and gave up and used this gem this time. I wanted to improve the fact that the event title appears every time between start_time and end_time, but it was difficult due to my lack of power. The class name of the element has no particular meaning. I misspell it here and there, but ... I think that even such a simple calendar will be better than mine depending on how you show it, so please try it.

Recommended Posts

Calendar implementation and conditional branching in Rails Gem simple calendar
[Rails] Introduce a simple calendar and insert a "confirmation screen" in additional events
Introduction and basic usage of Simple Calendar gem
This and that of conditional branching of rails development
Gem often used in Rails
View monthly calendar in Rails
java (conditional branching and repetition)
Implementation policy to dynamically save and display Timezone in Rails
Basics of conditional branching and return
Enable jQuery and Bootstrap in Rails 6 (Rails 6)
[rails] Login screen implementation in devise
Implemented hashtag search like Instagram and Twitter in Rails (no gem)
Implement simple login function in Rails
Remove "assets" and "turbolinks" in "Rails6".
CRUD features and MVC in Rails
[Rails] gem ancestry category function implementation
Implement share button in Rails 6 without using Gem
(Basic authentication) environment variables in rails and Docker
[Rails] Schedule management using Full Calendar Yesterday's implementation
[Rails] Implementation of retweet function in SNS application
[Nuxt / Rails] POST implementation using axios and devise_token_auth
[Rails] Implementation of "notify notification in some way"
[Rails] Implementation of batch processing using whenever (gem)
Simple notification function in Rails (only when followed)
[Rails] Ranking and pagination in order of likes
Implement a reservation system using Rails and simple calendar! Let's add validation to datetime!