nulltek
nulltek

Reputation: 3337

Scope to query last year's data

I've written a scope that returns all objects with a transfer_date from the beginning of the current year to the end of the current year.

scope :year, lambda { where("transfer_date BETWEEN ? AND ?", Time.zone.now.beginning_of_year, Time.zone.now.end_of_year) }

This works well and gives me the objects that I need. But now I'm looking to write a scope that does the same thing but for the previous year. I know there's no method in the Time class for beginning_of_last_year so I'm thinking that it might be better to define a class method instead of a scope.

If I wanted to return all objects with a date between the beginning of last year and the end of last year, what would be the best way to express this in Ruby?

I've written this as a scope but I think it can be cleaner:

scope :previous_year, lambda {where("transfer_date BETWEEN ? AND ?", Time.zone.now.beginning_of_year - 1.year, Time.zone.now.end_of_year - 1.year)}

Upvotes: 2

Views: 2000

Answers (3)

coreyward
coreyward

Reputation: 80041

There are a few optimizations I'd make here.

Since you already have ActiveSupport loaded and you're using it, make use of the ago method, and write something that's a little more flexible. You can also use a range and ActiveRecord can handle writing the appropriate query for your DB, no string substitution needed.

scope :from_year, ->(date) { where(transfer_date: date.beginning_of_year..date.end_of_year) }

# usage
Record.from_year(1.year.ago)

This is a lot less rigid. You can now easily query for records that are from 5 years ago without writing any new code. If you find yourself using last year in a lot of places, make it a convenience method:

def self.last_year
  from_year 1.year.ago
end

Upvotes: 4

Frank004
Frank004

Reputation: 228

I use this line of code

scope :last_year, lambda {where(transfer_date: 1.year.ago.all_year)}

irb(main):032:0> 1.year.ago.all_year
=> Thu, 01 Jan 2015 00:00:00 UTC +00:00..Thu, 31 Dec 2015 23:59:59 UTC +00:00

Upvotes: 0

S. A.
S. A.

Reputation: 3754

How about this:

(Time.zone.now - 1.year).beginning_of_year
(Time.zone.now - 1.year).end_of_year

Upvotes: 2

Related Questions