LoginSignup
18
20

More than 3 years have passed since last update.

Railsとsimple calendarを使って予約システムを実装!datetimeにバリデーションをつけよう!

Last updated at Posted at 2020-11-02

実装したい内容

gemのsimple calendarを使ってカレンダーに予約の予定を入れていく
rubyやRailsの基礎知識があること前提で話を進めていきます

開発環境

Rails 6.0.3
ruby 2.7.0

reservationsテーブルの追加

今回はミニアプリを作る想定をしreservationsテーブルを作成しname(string)とstart_time(datetime型)のカラムを追加していきます。

rails new calendar_app

まずはお決まりのrails new

bundle

bundle installも癖づけて行いましょう。

Gemfile
gem 'simple_calendar', '~> 2.0'
bundle

gemfileにsimple_calendarを追加したら再びbundle install

rails g scaffold reservationc name start_time:datetime

今回はスキャフォルドを使って簡単にアプリを実装していきたいと思います。

rails db:migrate

お決まりのrails db:migrateも忘れないように。

スクリーンショット 2020-11-02 23.30.30.png

rails sで http://localhost:3000/ にアクセス!
しっかり立ち上がっていることが確認できたら

routes.rb
root 'reservations#index'

ルートパスを予約の一覧ページに変更しておきましょう。
スクリーンショット 2020-11-02 23.33.42.png

続いてsimple_calendarのviewを整えていきます

rails g simple_calendar:views
create  app/views/simple_calendar
      create  app/views/simple_calendar/_calendar.html.erb
      create  app/views/simple_calendar/_month_calendar.html.erb
      create  app/views/simple_calendar/_week_calendar.html.erb

ファイルが3つ作成されたのですが今回はmouthを使用していきたいと思います。

application.css
 *= require simple_calendar
# simple_calendarのcssを読み込む
reservations.index.html.erb

<p id="notice"><%= notice %></p>

<h1>Reservations</h1>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Start time</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @reservations.each do |reservation| %>
      <tr>
        <td><%= reservation.name %></td>
        <td><%= reservation.start_time %></td>
        <td><%= link_to 'Show', reservation %></td>
        <td><%= link_to 'Edit', edit_reservation_path(reservation) %></td>
        <td><%= link_to 'Destroy', reservation, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<!-- ここから --!>
<%= month_calendar events: @reservations do |date, reservations| %>
  <%= date %>

  <% reservations.each do |reservation| %>
    <div>
      <%= reservation.start_time.hour %>:<%= reservation.start_time.min %>
      <%= reservation.name %>
    </div>
  <% end %>
<% end %>
<!-- ここまで追加 --!>

<%= link_to 'New Reservation', new_reservation_path %>

スクリーンショット 2020-11-02 23.49.48.png
カレンダーが表示できたかと思います!

スクリーンショット 2020-11-02 23.52.22.png

予約を追加するとしっかりとカレンダーにも反映されます♪

これだけではつまらないのでバリデーションを追加していきましょう。

特殊なバリデーションを自作する

今回は予約の数を制限したいので土日は予約不可。
過去の日付は選択できない
予約できる時間帯は13:15と19:15のみと言った物凄い特殊なバリデーションを組んでいきたいと思います!

reservation.rb
class Reservation < ApplicationRecord
  validates :name, presence: true
  validate :date_before_start
  validate :start_time_not_sunday
  validate :start_time_not_saturday
  validate :time_only
  validates :start_time, uniqueness: { message: 'は他のユーザーが予約しています' }

  def date_before_start
    errors.add(:start_time, "は過去の日付を選択できません") if start_time < Date.today
  end

  def start_time_not_sunday
    errors.add(:start_time, "は日曜日を選択できません") if start_time.sunday?
  end

  def start_time_not_saturday
    errors.add(:start_time, "は土曜日を選択できません") if start_time.saturday?
  end

  def time_only
    if hour_only_1 && min_only
      true
    elsif hour_only_2 && min_only
      true
    else
      errors.add(:start_time, "(時間)は13:15もしくは19:15になります")
    end
  end

  def hour_only_19
    start_time.hour == 19
  end

  def hour_only_13
    start_time.hour == 13
  end

  def min_only
    start_time.min == 15
  end
end

date_before_timeは過去の日付を選択できないことを表しています。
start_time_not_subdayとstart_time_notsaturdayで土日を予約不可とします!
start_time.sunday?などでdate_time(型は)日曜?ですか?みたいな感じに表すことができます!

ここからが本番!!
13:15分と19:15分の2つの時間に予約を限定していきます.

start_time.hourで時間を指定でき、start_time.minで分数を指定できるので
これを13時、19時、15分と限定していきます!

time_onlyメソッドを作成し時間を限定します!!
またstart_time をuniqqueness: trueにすることにより、同じ時間でも予約が不可になるので1日に取れる最大の予約数は2件となります!!

番外編

今回はかなり特殊な形だったのでバリデーションを自作していきましたが、datetimeのバリデーションには
validates_timelinessといった便利なgem があります!
https://github.com/adzap/validates_timeliness

# in Gemfile
gem 'validates_timeliness', '~> 5.0.0.beta1'

# Run bundler
$ bundle install

例えば予約時間を9時から5時までの間に限定したい場合は
validates_time :booked_at, between: ['9:00am', '5:00pm']
みたいな形に書くと簡単に実装できます!!

※このgemはrails5に対応したgemなのでrails6だとコンフリクトする可能性があります

18
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
20