1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Ruby on Rails: 営業日時の処理・表示に関する一般的な問題とその解決策

Last updated at Posted at 2024-03-05

問題1

Ruby on Railsの開発において、日付や時刻の扱いはよく遭遇する課題です。特に、日付や時刻を扱うアプリケーションでは、文字列とStringDateDateTimeTimeオブジェクト間の変換が必要になる場合が多々あります。不適切な変換やフォーマットのミスマッチは、期待しない動作やエラーの原因となり得ます。

この記事では、具体的なエラーの事例を取り上げつつ、その原因と解決策について解説します。

事例と問題点

Railsアプリケーションにおいて、ユーザーからの入力を基にサービスの提供可能性を判断する機能を実装している際、以下のようなTypeErrorが発生しました。

TypeError: no implicit conversion of ActiveSupport::Duration into String

このエラーは、文字列型の時刻データに対してActiveSupport::Durationオブジェクトを加算しようとしたときに発生します。原因は、時刻を表す文字列(例: "09:00")に、ActiveSupport::Duration(例: 60.minutes)を加算しようとしたためです。Rubyでは、文字列に対して直接時間を加算することはできません。

問題の解決

問題の解決には、文字列型の時刻データを適切なTimeオブジェクトに使用する必要がありました。具体的には、以下のコード変更により問題が解決しました。

# Before
# available_start_timesはTime型
<% available_start_times = calculate_available_start_times(@date, @company, total_duration) %>
 <%= form.select :start_time, available_start_times.map { |time| [time.strftime("%H:%M"), time] }, { include_blank: true }, { required: true } %>
# After
# available_start_timesはTime型
<% available_start_times = calculate_available_start_times(@date, @company, total_duration) %>
<%= form.select :start_time, @available_start_times.map { |time| [time, time] }, { include_blank: true }, { required: true } %>

変更後のコードでは、TimeオブジェクトをTimeオブジェクトとしてマッピングしています。

問題2

以下はRailsアプリで、サービスの提供可能性を判断し表示する機能を実装中に遭遇した問題です。
schedulesfor_customer_indexアクションではサービス提供可能性が正しく×として表示されるのに対し、reservationsconfirmアクションでの表示が全て×になるというものでした。

原因

この問題の原因は、@date変数が適切にDateオブジェクトとして扱われていなかったことにありました。具体的には、confirmアクション内で@dateを設定する際に、単に文字列として代入していました。

# Before
@date = params[:reservation][:date]

この状態では、@dateが文字列として扱われ、後続の処理(特に日付の比較や時間の計算)で期待通りの挙動を示さなかったため、サービス提供可能性の判定ロジックが誤った結果を返していました。

解決策

問題の解決には、@dateDate.parseを使用して、文字列からDateオブジェクトへと変換する処理を加えました。これにより、日付として正しく扱うことができるようになり、サービス提供可能性の判定が正確に行われるようになりました。

# After
@date = params[:reservation][:date].present? ? Date.parse(params[:reservation][:date]) : Date.today

この変更により、confirmアクション内でもfor_customer_indexアクションと同様に、サービス提供可能性が正しく×として表示されるようになりました。

解決策のポイント

型の確認と変換:日付や時刻を扱う際には、適切なデータ型を使用することが重要です。特に、文字列とDate/DateTime/Timeオブジェクト間での変換が必要な場合は、明示的な変換メソッド(例: Date.parse)を利用して型を一致させましょう。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?