Connor
Connor

Reputation: 4168

Rails instance variable based on time?

Quick question. If I have a Model, say Charities, that has a start_date and an end_date attribute, how can I set that to be the current_charity from a method in the Controller?

I know I'll have to do some kind of Charities.find(params[:something]), and will just have to set that current_charity equal to one that's start_date is >= the current date, and who's end_date is <= the current date (there is only one "current" one at a time). I've usually just found a Model by the params[:id], so this is new to me.

Thank you!

Upvotes: 2

Views: 457

Answers (3)

Thilo
Thilo

Reputation: 17735

Add a scope method in your model:

def self.current
  now = Time.now
  where("start_date <= ? AND ? <= end_date", now, now).first
end

Then in your controller:

current_charity = Charity.current

Upvotes: 5

Larry K
Larry K

Reputation: 49114

Remember to add indexes in your database for columns that you will often be using in searches.

Add indexes by adding a db migration.

Upvotes: 0

AlexChaffee
AlexChaffee

Reputation: 8252

Quick answer: search for the charity whose end_date is nil.

Longer answer: Your data model may not match your desired semantics. It seems to me that start_date is irrelevant here -- isn't the current charity the one whose end_date hasn't happened yet?

In general, one way to get the most recent X is to fetch all X's, sorted by descending date, and take the first one (or in SQL terms, use LIMIT 1). In ActiveRecord, it's something like this:

Charity.order("end_date DESC").first

though I'm a bit rusty on my Rails 3 AR syntax, and I don't think that query will solve your actual problem (though it does look kind of cool, amirite?).

Another solution is to denormalize -- add a current boolean field, and a before_save filter that sets self[:current] based on the logic you described. EDIT: Actually, that won't work here, since time marches on, and what is current will change outside the scope of an individual model's data.

My best advice is to write a lot of unit tests! Time-based logic is very tricky and it's easy to miss an edge case.

Upvotes: 1

Related Questions