DRY(a): Year After Year 28
I’m guilty of it. Many of you are likely guilty of it… and I know that several customers of our Rails Code Audit and Review service are guilty of it.
How many times have you realized (after a few months has passed) that your Copyright date/year on your web site was no longer current?
How many of you had the same problem last year? The year before?
Let me share some advice with you all… DRY (a)!
Don’t Repeat Yourself (again)!
This is really a simple problem to fix but when we’re busy tackling bigger problems… little things like this slip by. Don’t worry, you’re not the only one who was reminded by a colleague three months into the year that you forgot to update this.
On client projects, we have a handful of helpers that we drop into the application. We’re starting to extract more of these into plugins and will be releasing those as time permits. It just happened that I found myself looking at yet-another Rails code base this afternoon that was showing 2007 in the footer. An easily forgivable offense.. but if you’re going to go in there and change it (again), take a moment to do the right thing. ;-)
Our solution at Planet Argon on client projects is to create a basic view helper that renders the current year. This allows us to do the following.
<div id="footer">
© Copyright <%= current_year -%>. All Rights Reserved.
</div>
The helper code looks like:
# add to application_helper.rb
module ApplicationHelper
def current_year
Time.now.strftime('%Y')
end
end
Voila. Not rocket science.. is it?
Guess what? I’m getting really tired of adding this to every Rails project that I touch. So, I bottled this little gem into a new Rails plugin that we’ll just add to future projects.
Introducing Year after Year
This is really the smallest plugin that I could put together (and it includes specs!)
What does it provide you?
YearAfterYear will provide you a helper that will render the current year (dynamically)! That’s right… just add the plugin to your Rails application and you too can enjoy New Years 2009 without having to have a deployment ready with a one line change from 2008 to 2009!
To use.. add the following to any view from within Ruby on Rails.
<%= current_year -%>
Installation
As I’m using git, you’ll need to grab this and put it into vendor/plugins. That’s it!
You can grab it on GitHub!
- http://github.com/robbyrussell/year_after_year/
- Bugs / Feature Requests here
Happy New Years (8+ months early)!
Just a friendly reminder to not forget the small stuff… because your visitors will notice! ;-)
Updates…
I got a few requests for this to also provide a range of years for people who like to do: 2005-2007. So this is now provided as well.
year_range(start_year)
<%= year_range(2005) %> # => 2005-2008
Enjoying the content? Be sure to subscribe to my RSS feed.





Wow, that really is the smallest plugin ever. Though in my opinion it really should have an option for a “start date”. A lot of my code has something like, “Copyright 2004-2008” or some such on it. Not really necessary, but it’s a good way of tracking when a particular project first started. Then again, that would require some sort of a database lookup or something so then it would no longer be the world’s smallest plugin.
Shouldn’t you be able to pass in a starting year to generate a range for copyright coverage? “Copyright 2007 – 2008” If you’re starting in 2008, you’d want to do something like current_year(2008) so that come New Years it would spit out “2008 – 2009”.
(goes back to causing trouble elsewhere…)
What about Timezone support?
@alex / @josh:
I’ve just added
year_range... get off my back! ;-)@rick: no.
Hehe. What about using 08 instead of 2008?
@john: that might push the boundaries of what this plugin is capable of. I’ll think about it. In the meantime, feel free to fork it, and submit for inclusion. ;-)
Sorry…but, why not just put this in your Footer
<= Time.now.strftime(‘%Y’) -> ?
Nice plugin. I do the same thing for every project in my ApplicationHelper. It actually used to be my most embarassing code, due to how large it was compared to what it did.
I’m actually proud of it now, since I got it down to one line:
def copyright_dates(start_year = Date.today().year) [start_year, Date.today().year].sort.uniq.join(" - ") end@Chris: Nice, I’ve just modified the plugin to use your example.
@Robby: Woot! Résumé’d. Glad I could help.
Seriously… can someone tell me why you need a helper for this and not just put the code itself in your view. I can see why the range would be useful, but without it you are just wrapping Ruby syntax into a helper. I don’t see why you can’t just put <= Time.now.strftime(‘%Y’) -> in your view?
I’m more surprised no-one’s mentioned you can just use <%= Time.now.year %> .. which is even easier and perfectly readable to even a non-developer.
@Peter: Party pooper. Occam’s Razor party pooper.
+1 Peter
Also, it seems weird that you’d create a plugin for something so small. You still need to remember to add that particular plugin to all your apps.
-1 Robby, bad Robby
my god, another gem to load…. not memory footprint friendly…
This is not about rails or being DRY, this is about good practices when releasing a website. Just put a Time.now.year in your layout and you’re done.
Does this plugin have a rake task which combs through 500.html, 404.html and 422.html in public/ – examines them for last year’s number value, and replaces that value with this years?
@jerome: aww.. you hurt my feelings. i suppose my sarcasm/joke tags don’t stand out enough. However, if you find yourself adding the same code to each project then you’re repeating yourself.
My bad for not communicating more of my sarcasm into this.. my friends who first responded had context before I posted this (see first few comments).
My main concern is that people are hard-coding things like years and forgetting about them. Consider this an attempt to remind people to not forget about the little details on your site.
In regards to using a plugin like this, it’s a matter of consistency across applications. If our HTML/CSS people know that there are helpers they can rely on in each of our applications they don’t need to be bothered with remembering Time.now.year or .strftime formats.
..and as Matt just pointed out, 500, 404, 422 pages get left out in both situations. So there is still a problem to solve that I didn’t account for.
@Matt: Hah! That’s a good idea… those get overlooked too. Submit a patch! :-)
In any event, my goal was to remind people to not hard code things that should dynamic and we have a plethora of solutions posted now for this commonly overlooked issue.
[/serious-response]
Robby,
I was starting to wonder if you’d fell and hit your head and forgot everything that you knew about Ruby on Rails. Underneath the same code is getting called whether is be the plugin or the code in the view.
Our team has a rule for views and that’d be: No model calls! While Date or Time isn’t a Rails model, it isn’t something that we’d really wanting to invoke directly from a view. This is why we have helpers to provide easier-to-read helpers for editing HTML. Moving it into a plugin seems a bit overkill if you’re only working on a few projects a year but if you’re working on 40,50+ applications each year than it become tedious to copy these helpers into each of your application helpers.
So, it really depends on where you draw the line. Maybe helpers like this belong in Rails-code?
I don’t think it’s legally sound to just assert copyright every year if the work in question hasn’t been changed in a significant way.
Don’t break the law, Robby.
DRY (a)
Hahaha, I love it!
DRY (a)
Hahaha, I love it!
@BadRobbie:
Whoops I didn’t checked your tags :) However, I don’t forsee anything good teaching DRYness with a single Time.now.year to replace which is in a way enough DRY as I only use it in my layout (c’mon, it’s just a few bytes and it’s clean enough) and pretty meaningfull as well.
Regarding error pages, I do have the ol’good ExceptionNotifier plugin and 2 private methods I overwrite in application.rb
class ApplicationController < ActionController::Base include ExceptionNotifiable private def render_404 respond_to do |type| type.html { render :template => 'errors/404', :status => 404, :layout => true } type.all { render :nothing => true, :status => 404 } end end def render_500 respond_to do |type| type.html { render :template => 'errors/500', :status => 500, :layout => true } type.all { render :nothing => true, :status => 500 } end end endOf course, you have to tune your main layout so that it won’t be broken when rendering error pages: I meant no embedded code (MVC, remember?)
In case of really critical error, I still have a static public/500.html the proxy will use if rails is down or drunk.
BTW sorry if I hurt you; now I owe you a hug.
Seriously… Date.today.year
For a range? “2006-#{Date.today.year}”
o_O
Here’s a helper I wrote for one of my last projects:
Using the correct separator entity, and good for the next 91 years of this century and beyond :)
Whether it’s worth pluginising is up to you (my general feeling would be no, it’s not)
It might feel nice to have the current year on your site. However, there’s no legal reason or need to do so (I know, but it’s true) if you haven’t materially made changes to your site (i.e. rewrote code) that year. And actually, having the current date as copyright generated by code rather than written by a person might hurt your case were it in court!
Sorry, I am a bit confused. Do you really think it’s a good idea to have a copyright notice plugin? Of course the copyright notice in a shared footer is a no-brainer. But a plugin? Really? I am going to assume you might, but if not, then sorry.
As I was getting started with RoR, one of my little joys was seeing the reasonably good date/time implementations. Having come from Java where you have to do a whole bunch of stupid, unintuitive things, it seemed like a breath of fresh air. So I added the @copy; Time.now.year code in my footer. Is this not DRY enough?I love the DRY mantra, but like all assertions of “good programming practice” you have to balance the trade-off between actual value and the increase in complexity.
Having a copyright plugin that supports all known use-cases of copyright would be, as this conversation has begun to show, a fool’s errand. The only “canonical” aspect of this is the copyright symbol, which is neatly wrapped in an HTML entity. Everything else is variable. So why try to solve all variants of the problem in one place when it is almost certain that any specific user would use one and only one of them.
The good message here is: put your copyright message into the footer … ONCE, then forget it forever. That’s DRY.
Any plugin creates any number of dependencies and levels of indirection, which are synonymous with fragility and complexity. This cost is worthwhile when the plugin does something really useful and may get extended (one example: calendar_date_select). If the idea is all we need, we need to be happy that everyone is just putting their little spin on how they present their copyright, and that they are doing it once in their footer partial and let it go at that.
In the Java world, and in OO programming in general, it seems like developers tend to go off the deep end in making things abstract and indirect. Things start off pretty simple and straightforward. Then someone comes up with a “better” solution that solves more problems. But the code is more complex. And that is a cost: it’s harder to use, harder to test, bigger footprint, etc. What happened to KISS? In my mind, that is even more important than DRY.
Stop the madness and know when enough is enough!Tom :-)
Do it a little quicker just by using this in your view:
<%= Time.now.year %>