ActiveRecord tarihini arasında raylar


171

Bir gün içinde yapılan yorumları sorgulamam gerekiyor. Alan standart zaman damgalarının bir parçasıdır created_at. Seçilen tarih a date_select.

Bunu ActiveRecordyapmak için nasıl kullanabilirim ?

Gibi bir şeye ihtiyacım var:

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

Yanıtlar:


402

Şu anda kabul edilen cevabın Rails 3'te kullanımdan kaldırıldığını unutmayın. Bunun yerine bunu yapmalısınız:

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

Veya saf dize koşullarını kullanmak veya kullanmak zorundaysanız , şunları yapabilirsiniz:

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

9
Day.where (: reference_date => 6.months.ago..Time.now) çalışıyor, teşekkürler
boulder_ruby

4
Bu çok büyük bir nesne yaratmaz mı?
Kasper Grubbe

3
@KasperGrubbe, aralığı tek başına kullandıysanız, Rails sadece ilk ve son değerleri kullanır
Dex

4
@KasperGrubbe @Dex Bunu yapan Raylar değil. Ruby'deki Range sınıfı yalnızca alt ve üst sınırları kaydeder. Bu irb'de iyi çalışıyor: 1..1000000000000'Aralığı kendi başına kullanma' ile ne demek istediğin konusunda net değilim
Connor Clark

11
+1 Bunu bir kapsam da yapabiliriz: scope :between, -> (a, b) { where(created_at: a..b) }
rebagliatte

48

Şahsen daha okunabilir ve yeniden kullanılabilir hale getirmek için bir kapsam oluşturdu:

Comment.rb içinde bir kapsam tanımlayabilirsiniz:

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

Ardından aşağıdakiler arasında oluşturulan sorguyu sorgulamak için:

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

Umarım yardımcı olur.


4
Çok temiz bir yaklaşım ... mükemmel !!
Joseph N.

Bu yanıtı oylamaya geri dön çünkü bu konuyu araştırdım. Sözdiziminde yanlış tahmin #between?edildiğinde, bir aralığı kabul ettiği varsayılmıştır .
Tass

28

Rails 5.1 yeni bir tarih yardımcı yöntemi getirdi all_day, bakınız: https://github.com/rails/rails/pull/24930

>> 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 kullanıyorsanız, sorgu şöyle görünecektir:

Comment.where(created_at: @selected_date.all_day)

1
Şanlı. Bu aslında ActiveSupport geminin (ve daha sonra tüm ActiveRecord ekosisteminin) bir parçasıdır, bu yüzden Rails dışında da çalışır! Sadece require 'active_record've hazırsınız!
Ördeklerin Efendisi

24

Bu kodun sizin için çalışması gerekir:

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

Daha fazla bilgi için Zaman hesaplamalarına göz atın

Not: Bu kod kullanımdan kaldırılmıştır . Rails 3.1 / 3.2 kullanıyorsanız yanıttaki kodu kullanın


Tamam ama formdan şunu alıyorum: {"Yazılı_at (4i)" => "18", "Yazılı_at (5i)" => "56", "İçerik" => "rrrrrr", "Yazılı_at (1i)" = > "2010", "Yazılı_at (2i)" => "5", "Yazılı_at (3i)" => "4"} Nasıl başlangıç_of_dayı kullanmak için bir nesne oluşturabilirim?
rtacconi

İhtiyacım olan şey bu: purab.wordpress.com/2009/06/16/…
rtacconi

2
Bu yöntemi kabul edilen yanıt üzerinde seviyorum çünkü db düzeyi bir date()işleve bağlı değil; potansiyel olarak daha fazla db bağımsızdır.
Craig Walker

10

İşaretli cevabın işe yarayıp yaramadığını görmek için bu kodu çalıştırdım ve doğru şekilde almak için tarihler arasında geçiş yapmayı denemek zorunda kaldım. Bu işe yaradı--

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

Çıktının 36 olması gerektiğini düşünüyorsanız, bunu düşünün efendim, 3 kişiye 3 gün kaç gün?


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

5

3 yerine 2 noktayı kullanıyorum. Üç nokta size başlangıçta açık ve sonunda kapalı bir aralık verir, bu nedenle sonraki aralıklar için 2 sorgu yaparsanız, aynı satırı geri alamazsınız. her ikisi de.

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 []> 

Ve evet, her zaman bir kapsam kullanmak güzel!


4

Sadece bir gün almak istiyorsanız, bu şekilde daha kolay olurdu:

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

4

birkaç yol var. Bu yöntemi kullanabilirsiniz:

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

Veya bu:

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

4

Bu bence varsayılan bir aktif kayıt davranışı olmalıdır. Özellikle zaman dilimleri söz konusu olduğunda sorgulama tarihleri ​​zordur.

Her neyse, kullanıyorum:

  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
  }

1

Tarihler arasındaki kayıtları bulmak için gem'in altında kullanabilirsiniz,

Bu taş kullanımı oldukça kolay ve daha açık Yıldız tarafından bu taş ve API daha açık ve belgelerini de kullanıyorum iyi açıkladı.

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

Burada alanımızı da geçebilirsin Post.by_month("January", field: :updated_at)

Lütfen belgelere bakın ve deneyin.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.