web-dev-qa-db-ja.com

Rails ActiveRecord date between

1日以内に作成されたコメントをクエリする必要があります。フィールドは標準タイムスタンプの一部であり、created_atです。選択された日付はdate_selectから来ています。

ActiveRecordを使用してそれを行うにはどうすればよいですか?

私のようなものが必要です:

"SELECT * FROM comments WHERE created_at BETWEEN '2010-02-03 00:00:00' AND '2010-02-03 23:59:59'"
155
rtacconi

現在受け入れられている回答はRails 3で非推奨になっていることに注意してください。代わりにこれを行う必要があります。

Comment.where(:created_at => @selected_date.beginning_of_day..@selected_date.end_of_day)

または、 純粋な文字列条件 を使用する必要がある場合、または使用する必要がある場合は、次の操作を実行できます。

Comment.where('created_at BETWEEN ? AND ?', @selected_date.beginning_of_day, @selected_date.end_of_day)
372
ndbroadbent

個人的にスコープを作成して、読みやすく再利用できるようにしました。

Comment.rbで、スコープを定義できます。

scope :created_between, lambda {|start_date, end_date| where("created_at >= ? AND created_at <= ?", start_date, end_date )}

次に、次の間に作成されたクエリ:

@comment.created_between(1.year.ago, Time.now)

それが役に立てば幸い。

43
Marshall Shen

このコードはあなたのために働くはずです:

Comment.find(:all, :conditions => {:created_at => @selected_date.beginning_of_day..@selected_date.end_of_day})

詳細については、 時間の計算 をご覧ください。

注:このコードは 非推奨 です。 Rails 3.1/3.2を使用している場合は、回答のコードを使用してください

23
Irukandji

Rails 5.1では、新しい日付ヘルパーメソッドall_dayが導入されました。参照: https://github.com/Rails/rails/pull/249

>> Date.today.all_day
=> Wed, 26 Jul 2017 00:00:00 UTC +00:00..Wed, 26 Jul 2017 23:59:59 UTC +00:00

Rails 5.1を使用している場合、クエリは次のようになります。

Comment.where(created_at: @selected_date.all_day)
21
Bismark

私はこのコードを実行して、チェックされた回答が機能するかどうかを確認し、日付を入れ替えて正しく解決する必要がありました。これは働いた-

Day.where(:reference_date => 3.months.ago..Time.now).count
#=> 721

出力が36であるべきだと思っているなら、これを考慮してください。

10
boulder_ruby
Comment.find(:all, :conditions =>["date(created_at) BETWEEN ? AND ? ", '2011-11-01','2011-11-15'])
6
kaushal sharma

2の代わりに3つのドットを使用しています。3つのドットは、最初は開いていて最後は閉じている範囲を提供するため、後続の範囲に対して2つのクエリを実行すると、同じ行を戻すことはできません両方。

2.2.2 :003 > Comment.where(updated_at: 2.days.ago.beginning_of_day..1.day.ago.beginning_of_day)
Comment Load (0.3ms)  SELECT "comments".* FROM "comments" WHERE ("comments"."updated_at" BETWEEN '2015-07-12 00:00:00.000000' AND '2015-07-13 00:00:00.000000')
=> #<ActiveRecord::Relation []> 
2.2.2 :004 > Comment.where(updated_at: 2.days.ago.beginning_of_day...1.day.ago.beginning_of_day)
Comment Load (0.3ms)  SELECT "comments".* FROM "comments" WHERE ("comments"."updated_at" >= '2015-07-12 00:00:00.000000' AND "comments"."updated_at" < '2015-07-13 00:00:00.000000')
=> #<ActiveRecord::Relation []> 

そして、はい、スコープを使用するのは常にいいです!

5
nroose

これには、デフォルトのアクティブレコードの動作があるはずです。特にタイムゾーンが関係する場合、日付のクエリは困難です。

とにかく、私は使用します:

  scope :between, ->(start_date=nil, end_date=nil) {
    if start_date && end_date
      where("#{self.table_name}.created_at BETWEEN :start AND :end", start: start_date.beginning_of_day, end: end_date.end_of_day)
    elsif start_date
      where("#{self.table_name}.created_at >= ?", start_date.beginning_of_day)
    elsif end_date
      where("#{self.table_name}.created_at <= ?", end_date.end_of_day)
    else
      all
    end
  }
4

いくつかの方法があります。次の方法を使用できます。

start = @selected_date.beginning_of_day
end = @selected_date.end_of_day
@comments = Comment.where("DATE(created_at) BETWEEN ? AND ?", start, end)

またはこれ:

@comments = Comment.where(:created_at => @selected_date.beginning_of_day..@selected_date.end_of_day)
4
ben

1日だけを取得したい場合は、この方法が簡単です。

Comment.all(:conditions => ["date(created_at) = ?", some_date])
4
klew

以下のgemを使用して、日付間のレコードを検索できますが、

このGemは非常に使いやすく、より明確に By star このGemとAPIをより明確に使用し、ドキュメントもよく説明されています。

Post.between_times(Time.zone.now - 3.hours,  # all posts in last 3 hours
                  Time.zone.now)

ここでフィールドを渡すこともできますPost.by_month("January", field: :updated_at)

ドキュメントを参照して、試してください。

1
Jenorish