Rails와 simple calendar를 사용하여 예약 시스템을 구현! datetime에 밸리데이션을 붙이자!

구현하고 싶은 내용



gem의 simple calendar를 사용하여 캘린더에 예약 예정을 넣습니다.
루비와 레일의 기초 지식이 있다는 전제하에 이야기를 진행합니다.

개발 환경



Rails 6.0.3
루비 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도 잊지 않도록.



rails s에서 http://localhost:3000/에 액세스!
확실히 일어나는 것을 확인할 수 있다면

routes.rb
root 'reservations#index'

루트 경로를 예약 목록 페이지로 변경합시다.


계속해서 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 %>


캘린더를 볼 수 있을까 생각합니다!



예약을 추가하면 확실히 캘린더에도 반영됩니다♪

이것만으로는 지루하지 않기 때문에 밸리데이션을 추가해 갑시다.

특수한 밸리데이션을 자작



이번에는 예약 수를 제한하고 싶기 때문에 토, 일, 예약 불가.
과거 날짜를 선택할 수 없음
예약할 수 있는 시간대는 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 분의 두 시간으로 예약을 제한합니다.

start_time.hour에서 시간을 지정할 수 있고 start_time.min에서 분수를 지정할 수 있으므로
이것을 13시, 19시, 15분으로 한정하겠습니다!

time_only 메서드를 만들고 시간을 제한합니다! !
또한 start_time 을 uniqqueness: true 로 하는 것으로, 같은 시간이라도 예약이 불가하게 되므로 하루에 취할 수 있는 최대의 예약수는 2건이 됩니다! !

번외편



이번에는 상당히 특수한 형태였기 때문에 밸리데이션을 자작해 갔습니다만, datetime의 밸리데이션에는
validates_timeliness와 같은 편리한 gem이 있습니다!
htps : // 기주 b. 코 m / d d p / ゔ ぃ ㄱ s_ Chime ぃ 네 s
# 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이라고 컨플릭트할 가능성이 있습니다

좋은 웹페이지 즐겨찾기