A note to all rails developers, new and old. If you’re not following Ryan Bates’ Railcasts, you should be.
I follow a variey of rails blogs and lean on a number of resources quite regularly, but the Railscasts are consistently the most useful. There are now over 100 railscast, each one a roughly 5 minute screencast outlining the solution to some problem.
A recent cast showed how to create a site wide announcement that each user could mark as read individually. This is a great, non-intrusive way to communicate notices with users.
The screencast details how to do it. I was able to implement this on a site in a very short period of time. I made some modifications which make it work better within my site. I do have one suggestion to improve it overall. To track whether a message had been read/should be shown Ryan uses the session. Sessions expire in the near future, and if using a db store, should be wiped daily. If your users don’t visit daily, you will want to create a message that hangs around for a week or 2. In this case, a session variable won’t work. Instead, you can store the info in a cookie and set a delayed expire time on it. (By default, cookies expire with the session in rails).
Before reading how to store this info in a cookie you should watch the screencast. Once you’ve implemented everything like Ryan’s demo, there are just 3 small changes to use cookies and hence have a longer memory.
1. In your controller, set the cookie:
def hide_announcement
cookies[:announcement_hide_time] ={ :value => Time.now.to_s , :expires => 2.weeks.from_now }
end
2. In your helper method, read the value from the cookie.
def current_announcements
@announcements ||= Announcement.current_announcements(cookies[:announcement_hide_time])
end
3. In the announcement controller you need to parse the time since it is stored as a string in the cookie
def self.current_announcements(hide_time)
with_scope :find => { :conditions => "starts_at <= now() AND ends_at >= now()" } do
if hide_time
time = Time.parse(hide_time)
find(:all, :conditions => ["updated_at >= ?", time])
else
find(:all)
end
end
end

