質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

2回答

1276閲覧

simple_calendarを利用して予約システムを作成していたがTypeErrorが発生する

keiino0425

総合スコア2

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2022/11/14 13:06

前提

Railsで予約システムを作っています。
https://qiita.com/sssssatou/items/2e6606e3ddf9b246a0fb
こちらの記事を参考にアレンジしているのですが、途中でエラーが発生してしまいました。

実現したいこと

ユーザー(生徒)でログイン

授業を受けたい先生を選ぶ

その先生のスケジュールの中から空いている時間は予約を入れることができる

参考にしている記事(https://qiita.com/sssssatou/items/2e6606e3ddf9b246a0fb#3%E4%BA%88%E7%B4%84%E3%81%AE%E6%9C%89%E7%84%A1%E3%81%AB%E3%82%88%E3%81%A3%E3%81%A6%E7%94%BB%E9%9D%A2%E3%81%AE%E8%A1%A8%E7%A4%BA%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B)
では予約の有無を探すときに

reservations_helper.rb

1module ReservationsHelper 2 3 # 略 4 5 def check_reservation(reservations, day, time) 6 result = false 7 reservations_count = reservations.count 8 # 取得した予約データにdayとtimeが一致する場合はtrue,一致しない場合はfalseを返します 9 if reservations_count > 1 10 reservations.each do |reservation| 11 result = reservation[:day].eql?(day.strftime("%Y-%m-%d")) && reservation[:time].eql?(time) 12 return result if result 13 end 14 elsif reservations_count == 1 15 result = reservations[0][:day].eql?(day.strftime("%Y-%m-%d")) && reservations[0][:time].eql?(time) 16 return result if result 17 end 18 return result 19 end 20end

となっており、開始時間が一致している予約のみが反応し、その開始時間に予約を入れられないようになります。

しかし、私が作ろうと思っているシステムは予約の開始時間から終了時間まで、新規予約を入れることができないものです。それを作るために

reservations_helper.rb

1if reservations_count > 1 2 reservations.each do |reservation| 3 result = reservation[:day].eql?(day.strftime("%Y-%m-%d")) && reservation[:time].eql?(time) 4 return result if result 5 end 6 elsif reservations_count == 1 7 result = reservations[0][:day].eql?(day.strftime("%Y-%m-%d")) && reservations[0][:time].eql?(time) 8 return result if result 9 end 10 return result

この部分を

reservations_helper.rb

1if reservations_count > 1 2 reservations.each do |reservation| 3 result = reservation[:start_time] <= DateTime.parse(day + " " + time + " " + "JST") && DateTime.parse(day + " " + time + " " + "JST") <= reservation[:end_time] 4 return result if result 5 end 6 elsif reservations_count == 1 7 result = reservations[0][:start_time] == DateTime.parse(day + " " + time + " " + "JST") && DateTime.parse(day + " " + time + " " + "JST") <= reservations[0][:end_time] 8 return result if result 9 end 10 return result

このように変更しました。
しかし、TypeErrorが発生してしまいます。
イメージ説明

rails cで
reservation[:start_time] <= DateTime.parse(day + " " + time + " " + "JST") && DateTime.parse(day + " " + time + " " + "JST") <= reservation[:end_time]
をしましたがTrueもしくはFalseが返ってくるため、間違っていないと思うのですが、解決策などアドバイスをお願いいたします。

該当のソースコード

reservations_helper.rb

1module ReservationsHelper 2 def times 3 times = ["9:00", 4 "9:30", 5 "10:00", 6 "10:30", 7 "11:00", 8 "11:30", 9 "13:00", 10 "13:30", 11 "14:00", 12 "15:00", 13 "15:30", 14 "16:00", 15 "16:30", 16 "17:00", 17 "17:30", 18 "18:00", 19 "19:00", 20 "19:30", 21 "20:00" 22 ] 23 end 24 25 def check_reservation(reservations, day, time) 26 result = false 27 reservations_count = reservations.count 28 if reservations_count > 1 29 reservations.each do |reservation| 30 result = reservation[:start_time] <= DateTime.parse(day + " " + time + " " + "JST") && DateTime.parse(day + " " + time + " " + "JST") <= reservation[:end_time] 31 return result if result 32 end 33 elsif reservations_count == 1 34 result = reservations[0][:start_time] == DateTime.parse(day + " " + time + " " + "JST") && DateTime.parse(day + " " + time + " " + "JST") <= reservations[0][:end_time] 35 return result if result 36 end 37 return result 38 end 39end

index.html.erb

1<div class="container"> 2 <div class="row"> 3 <div class="col-12 text-center"> 4 <h1><%= @teacher.teacher_name %>先生予約画面</h1> 5 <p>3ヶ月先まで予約することができます。</p> 6 </div> 7 <div class="col-12 mt-3"> 8 <%= week_calendar events: @reservations do |date, reservations| %> 9 <%= date.day %> 10 <% end %> 11 </div> 12 </div> 13</div>

_week_calendar.html.erb

1<div class="simple-calendar"> 2 <div class="calendar-heading"> 3 <%= link_to "先週", calendar.url_for_previous_view %> 4 <% if calendar.number_of_weeks == 1 %> 5 <span class="calendar-title"><%= t('simple_calendar.week', default: 'Week') %> <%= calendar.week_number %></span> 6 <% else %> 7 <span class="calendar-title"><%= t('simple_calendar.week', default: 'Week') %> <%= calendar.week_number %> - <%= calendar.end_week %></span> 8 <% end %> 9 <%= link_to "来週", calendar.url_for_next_view %> 10 <% reservations = Reservation.where(teacher_id: params[:teacher_id]).reservations_after_three_month %> 11 </div> 12 13 <table class="table table-striped"> 14 <thead> 15 <tr> 16 <th>時間</th> 17 <% date_range.slice(0, 7).each do |day| %> 18 <th><%= t('date.abbr_day_names')[day.wday] %></th> 19 <% end %> 20 </tr> 21 </thead> 22 23 <tbody> 24 <% date_range.each_slice(7) do |week| %> 25 <tr> 26 <td></td> 27 <% week.each do |day| %> 28 <%= content_tag :td, class: calendar.td_classes_for(day) do %> 29 <% if defined?(Haml) && respond_to?(:block_is_haml?) && block_is_haml?(passed_block) %> 30 <% capture_haml(day, sorted_events.fetch(day, []), &passed_block) %> 31 <% else %> 32 <% passed_block.call day, sorted_events.fetch(day, []) %> 33 <% end %> 34 <% end %> 35 <% end %> 36 </tr> 37 <% times.each do |time| %> 38 <tr> 39 <td><%= time %></td> 40 <% week.each do |day| %> 41 <td> 42 <% if check_reservation(reservations, day, time) %> 43 <%= '×' %> 44 <% else %> 45 <%= link_to new_user_teacher_reservation_path(current_user, @teacher.id, day: day, time: time) do %> 46 <%= '○' %> 47 <% end %> 48 <% end %> 49 </td> 50 <% end %> 51 </tr> 52 <% end %> 53 <% end %> 54 </tbody> 55 </table> 56</div> 57

reservation.rb

1class Reservation < ApplicationRecord 2 belongs_to :user 3 belongs_to :teacher 4 def self.reservations_after_three_month 5 # 今日から3ヶ月先までのデータを取得 6 reservations = Reservation.all.where("day >= ?", Date.current).where("day < ?", Date.current >> 3).order(day: :desc) 7 # 配列を作成し、データを格納 8 # DBアクセスを減らすために必要なデータを配列にデータを突っ込んでます 9 reservation_data = [] 10 reservations.each do |reservation| 11 reservations_hash = {} 12 reservations_hash.merge!(day: reservation.day.strftime("%Y-%m-%d"), time: reservation.time) 13 reservation_data.push(reservations_hash) 14 end 15 reservation_data 16 end 17end 18

reservations_controller.rb

1class ReservationsController < ApplicationController 2 before_action :authenticate_user! 3 def index 4 @reservations = Reservation.all.where("day >= ?", Date.current).where("day < ?", Date.current >> 3).where(teacher_id: params[:teacher_id]).order(day: :desc) 5 @teacher = Teacher.find(params[:teacher_id]) 6 end 7 8 def choice 9 @teachers = Teacher.all 10 end 11 12 def new 13 @user = current_user 14 @teacher = Teacher.find(params[:teacher_id]) 15 @reservation = Reservation.new 16 @day = params[:day] 17 @time = params[:time] 18 @teacher_id = params[:teacher_id] 19 @start_time = DateTime.parse(@day + " " + @time + " " + "JST") 20 @end_time = @start_time + 90.minutes 21 end 22 23 def show 24 @reservation = Reservation.find(params[:id]) 25 end 26 27 def create 28 @reservation = Reservation.new(reservation_params) 29 if @reservation.save 30 redirect_to user_teacher_reservation_path(@reservation.user_id, @reservation.teacher_id, @reservation.id) 31 else 32 render :new 33 end 34 end 35 36 private 37 def reservation_params 38 params.require(:reservation).permit(:day, :time, :user_id, :teacher_id, :start_time, :end_time) 39 end 40end 41

schema.rb

1# This file is auto-generated from the current state of the database. Instead 2# of editing this file, please use the migrations feature of Active Record to 3# incrementally modify your database, and then regenerate this schema definition. 4# 5# This file is the source Rails uses to define your schema when running `bin/rails 6# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to 7# be faster and is potentially less error prone than running all of your 8# migrations from scratch. Old migrations may fail to apply correctly if those 9# migrations use external dependencies or application code. 10# 11# It's strongly recommended that you check this file into your version control system. 12 13ActiveRecord::Schema.define(version: 2022_11_14_060848) do 14 15 create_table "reservations", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| 16 t.date "day", null: false 17 t.string "time", null: false 18 t.bigint "user_id", null: false 19 t.bigint "teacher_id", null: false 20 t.datetime "start_time", null: false 21 t.datetime "created_at", precision: 6, null: false 22 t.datetime "updated_at", precision: 6, null: false 23 t.datetime "end_time", null: false 24 end 2526 27end 28

補足情報(FW/ツールのバージョンなど)

ruby '2.7.5'
rails '6.1.6'
simple_calendar '2.0'

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

no1knows

2022/11/14 22:11

> TrueもしくはFalseが返ってくるため、間違っていないと思うのですが とのことですが、エラー文は下記のようになっています。まずはここから調べてみてはいかがでしょうか? expected numeric rails またエラー画面は、画像をはるのではなく、コードをコピーしてください。
winterboum

2022/11/14 23:15

>またエラー画面は、画像をはるのではなく、コードをコピーしてください。 です。 潰れてしまって読めないし、検索もできないし
keiino0425

2022/11/15 04:17

アドバイスありがとうございます!以後気をつけます!
guest

回答2

0

result = reservations[0][:start_time] == DateTime.parse(day + " " + time + " " + "JST") && DateTime.parse(day + " " + time + " " + "JST") <= reservations[0][:end_time]

reservations[0][:start_time] は String で DateTime.parse(day + " " + time + " " + "JST") は DateTime です。
ので == できないということでしょう。
参考では reservation[:day].eql?(day.strftime("%Y-%m-%d")) と両方Stringで比べてます。

rails cで 通ったということですが、その時の reservations や day、 time をどのように設定したのか、という所が明らかでないので 通った原因はわかりません。

投稿2022/11/14 23:22

winterboum

総合スコア23329

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

keiino0425

2022/11/15 04:30

回答ありがとうございます!classが違うので比較できないんですね! rails cでは Reservation.find(7)[:start_time] <= DateTime.parse("2022-11-18" + " " + "10:00" + " " + "JST") && DateTime.parse("2022-11-18" + " " + "10:00" + " " + "JST") <= Reservation.find(7)[:end_time] として行いましたがTrueが返ってきました。 (Reservation.find(7)[:start_time]は Fri, 18 Nov 2022 10:00:00.000000000 JST +09:00 Reservation.find(7)[:end_time]は Fri, 18 Nov 2022 11:30:00.000000000 JST +09:00) また、Reservation.find(7)[:start_time].class としたところ、Stringが表示されるかと思いましたが ActiveSupport::TimeWithZoneが表示されました。 これがStringではない理由もわからないのですが教えていただいてよろしいでしょうか。 お願いいたします。
keiino0425

2022/11/15 05:52

>> reservations[0][:start_time] は String で DateTime.parse(day + " " + time + " " + "JST") は DateTime です。 ので == できないということでしょう。 参考では reservation[:day].eql?(day.strftime("%Y-%m-%d")) と両方Stringで比べてます。 と言われていますがscheme.rbで定義されているように reservationのdayはDateクラス、start_timeはDatetimeクラスなのにStringで表示されるのはなぜなのでしょうか。 rails c でそれぞれ表示すると Reservation.find(7)[:day].classはDate, Reservation.find(7)[:start_time].classはActiveSupport::TimeWithZoneでした。 理由を教えていただけますと幸いです。
guest

0

自己解決

pry-railsを使ってデバックをしました。

[2] pry(#<#<Class:0x0000aaab14413fb0>>)> Time.zone.parse(day + " " + time + " " + "JST") TypeError: expected numeric from /usr/local/bundle/gems/activesupport-6.1.7/lib/active_support/core_ext/date/calculations.rb:94:in `+'

となっていたためparseの中が上手く処理できていないのではないかと思い、

Time.zone.parse(day.to_s + " " + time + " " + "JST")

としたところ上手く行きました。

投稿2022/11/16 10:26

keiino0425

総合スコア2

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問