Techioz Blog

Date.parse Rails のクエリ

概要

私は、event.start_time を「2023-11-07」として記録する必要があるカレンダー gem を使用しています。

start_time と、event.rained_out == false に基づいて、今月と先月のすべてのイベントを検索する必要があります。

event.start_time[0,4].to_i == Time.now.year && event.start_time[5,2] == Time.now.month || event.start_time[5,2] == Time.now.month && event.rained_out== false

これを達成するために activerecord クエリを使用する方法がわかりません。

Event.where("start_time[5,2].to_i = ?", Time.now.month)

構文エラーです

解決策

データベースの start_time 列の型が文字列であり、日付が前月または今月を示す特定の文字列で始まるすべての行を検索したいことを理解しています。

まず、次のように、書式設定された日付文字列プレフィックスの範囲を作成します。

date_prefixes = [1.month.ago, 1.month.since].map { |time| time.strftime('%Y-%m') }
#=> ["2023-10", "2023-12"]
prefixes_range = Range.new(*date_prefixes, exclude_end = true)
#=> "2023-10"..."2023-12"

次に、その範囲を ActiveRecord クエリに渡して、その範囲に含まれるすべての文字列を検索できます。これは、exclude_end = true であるため、2023-10 または 2023-11 で始まるすべての開始日になりますが、2023-12 では始まりません。

Event.where(start_time: prefix_range)

これは基本的に次のような SQL クエリに変換されます。

start_date >= '2023-10' AND start_date < '2023-12'

すべてをスコープにまとめると、次のようになります。

# in app/models/event.rb
scope :started_this_or_previous_month, -> {
  where(
    start_date: Range.new(
      *[1.month.ago, 1.month.since].map { |t| t.strftime('%Y-%m') }, true
    )
  )
}

# use scope like this:
Event.started_this_or_previous_month.where(rained_out: false)

ところで。使用している gem で start_date が文字列である必要がある場合でも。 start_at または start_on のような datetime 型または date 型の列をテーブルに追加し、両方の列の同期を保つことを検討することをお勧めします。そうすれば、データベースのクエリがはるかに簡単になります。