Reputation: 3814
I have a Rails 3 application that is a basic intranet for our company. I have an announcement controller which checks for any announcements that have been created with a scheduled date that matches the current date.
class Announcement < ActiveRecord::Base
scope :active, lambda {
where("starts_at <= ? AND ends_at >= ?", Time.now.utc, Time.now.utc)
}
scope :since, lambda { |hide_time|
where("updated_at > ? OR starts_at > ?", hide_time.utc, hide_time.utc) if hide_time
}
def self.display(hide_time)
active.since(hide_time)
end
end
However, most announcement will be deleted within a week or so of the scheduled end date. All other announcements are simple Happy Birthday messages to staff members. Due to the way we are using the announcement system, it seems sensible to only check against the day/month and not the year, as birthday messages etc. will be annual.
What would the simplest way to 'ignore' the year in my controller code?
UPDATE
I have updated the controller code to the below code, however, announcements no longer hide after the end datetime.
class Announcement < ActiveRecord::Base
scope :active, lambda {
where("day(starts_at) <= ?
AND month(starts_at) <= ?
AND day(ends_at) >= ?
AND month(ends_at) >= ?",
Time.now.utc.day,
Time.now.utc.month,
Time.now.utc.day,
Time.now.utc.month)
}
scope :since, lambda { |hide_time|
where("day(starts_at) > ?
AND month(starts_at) > ?",
hide_time.utc.day, hide_time.utc.month) if hide_time
}
def self.display(hide_time)
active.since(hide_time)
end
end
An example record:
22, 'Test Announcement', 'This is a test announcement, please ignore it. Seriously - stop reading.', '2012-06-25 13:40:00', '2012-06-25 13:55:00', '2012-06-25 13:47:23', '2012-06-25 13:52:15');
Even though I have set :exclude_year on the input select boxes for the datetime fields it still puts the current year in.
Upvotes: 0
Views: 673
Reputation: 27114
Couple things. You should be using AND not OR if I understand you correctly, you want the time to fall between those to items. 2nd thing is you need to specify that it is at the beginning of the day and the end of the day. Right now it's just being set to the now which doesn't really say the expanse of 24 hours very clearly :
class Announcement < ActiveRecord::Base
scope :active, lambda {
where('starts_at < ? AND ends_at > ?', Time.zone.now.end_of_day, Time.zone.now.beginning_of_day)
}
scope :since, lambda { |hide_time|
where('updated_at > ? AND starts_at > ?', Time.zone.now.end_of_day, Time.zone.now.beginning_of_day)
}
Upvotes: 0
Reputation: 1479
If you are using MySQL database you could use its day() and month() methods. I don't know if these methods can be found for other databases as well. So doing it this way may make your code become dependent on the database server.
scope :active, lambda {
where("day(starts_at) <= ?
AND month(starts_at) <= ?
AND day(ends_at) >= ?
AND month(ends_at) >= ?",
Time.now.utc.day,
Time.now.utc.month,
Time.now.utc.day,
Time.now.utc.month)
}
Upvotes: 1