Read my latest article: Planet Argon Blog (posted Wed, 17 Feb 2010 15:11:00 GMT)

DRY(a): Year After Year

Posted by Robby Russell Tue, 25 Mar 2008 03:05:00 GMT

37 comments Latest by Facepalm Fri, 06 Mar 2009 18:37:09 GMT

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">
    &copy; 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!

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)

Example:

  <%= year_range(2005) %> # => 2005-2008
Subscribe to my RSS feed Enjoying the content? Be sure to subscribe to my RSS feed.
Comments

Leave a response

  1. Avatar
    Alex Tue, 25 Mar 2008 04:12:45 GMT

    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.

  2. Avatar
    josh Tue, 25 Mar 2008 04:16:03 GMT

    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…)

  3. Avatar
    rick Tue, 25 Mar 2008 04:20:49 GMT

    What about Timezone support?

  4. Avatar
    Robby Russell Tue, 25 Mar 2008 04:37:29 GMT Recommend me on Working with Rails

    @alex / @josh:

    I’ve just added year_range... get off my back! ;-)

    @rick: no.

  5. Avatar
    John Tue, 25 Mar 2008 04:51:38 GMT

    Hehe. What about using 08 instead of 2008?

  6. Avatar
    Robby Russell Tue, 25 Mar 2008 04:52:59 GMT Recommend me on Working with Rails

    @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. ;-)

  7. Avatar
    http://blog.ra66i.org Tue, 25 Mar 2008 10:57:46 GMT

    Surely this is completely pointless, I mean no rails programmer (or customer) died over 20 years ago.

    http://en.wikipedia.org/wiki/Copyright#Duration

    Legally this is pointless, it’s just aesthetic. Am I missing something Robby? I mean you talk about it so sternly, using words like ‘guilty’ and ‘offense’...

    just $0.02

  8. Avatar
    http://blog.ra66i.org Tue, 25 Mar 2008 10:57:51 GMT

    Surely this is completely pointless, I mean no rails programmer (or customer) died over 20 years ago.

    http://en.wikipedia.org/wiki/Copyright#Duration

    Legally this is pointless, it’s just aesthetic. Am I missing something Robby? I mean you talk about it so sternly, using words like ‘guilty’ and ‘offense’...

    just $0.02

  9. Avatar
    http://blog.ra66i.org Tue, 25 Mar 2008 10:57:54 GMT

    Surely this is completely pointless, I mean no rails programmer (or customer) died over 20 years ago.

    http://en.wikipedia.org/wiki/Copyright#Duration

    Legally this is pointless, it’s just aesthetic. Am I missing something Robby? I mean you talk about it so sternly, using words like ‘guilty’ and ‘offense’...

    just $0.02

  10. Avatar
    http://blog.ra66i.org Tue, 25 Mar 2008 10:58:12 GMT

    Surely this is completely pointless, I mean no rails programmer (or customer) died over 20 years ago.

    http://en.wikipedia.org/wiki/Copyright#Duration

    Legally this is pointless, it’s just aesthetic. Am I missing something Robby? I mean you talk about it so sternly, using words like ‘guilty’ and ‘offense’...

    just $0.02

  11. Avatar
    http://blog.ra66i.org Tue, 25 Mar 2008 10:58:14 GMT

    Surely this is completely pointless, I mean no rails programmer (or customer) died over 20 years ago.

    http://en.wikipedia.org/wiki/Copyright#Duration

    Legally this is pointless, it’s just aesthetic. Am I missing something Robby? I mean you talk about it so sternly, using words like ‘guilty’ and ‘offense’...

    just $0.02

  12. Avatar
    http://blog.ra66i.org Tue, 25 Mar 2008 10:58:20 GMT

    Surely this is completely pointless, I mean no rails programmer (or customer) died over 20 years ago.

    http://en.wikipedia.org/wiki/Copyright#Duration

    Legally this is pointless, it’s just aesthetic. Am I missing something Robby? I mean you talk about it so sternly, using words like ‘guilty’ and ‘offense’...

    just $0.02

  13. Avatar
    http://blog.ra66i.org Tue, 25 Mar 2008 10:59:33 GMT

    Surely this is completely pointless, I mean no rails programmer (or customer) died over 20 years ago.

    http://en.wikipedia.org/wiki/Copyright#Duration

    Legally this is pointless, it’s just aesthetic. Am I missing something Robby? I mean you talk about it so sternly, using words like ‘guilty’ and ‘offense’...

    just $0.02

  14. Avatar
    Jake Tue, 25 Mar 2008 13:58:28 GMT

    Sorry…but, why not just put this in your Footer

    <= Time.now.strftime(‘%Y’) -> ?

  15. Avatar
    Chris Doggett Tue, 25 Mar 2008 14:17:23 GMT

    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
    
  16. Avatar
    Robby Russell Tue, 25 Mar 2008 14:37:24 GMT Recommend me on Working with Rails

    @Chris: Nice, I’ve just modified the plugin to use your example.

  17. Avatar
    Chris Doggett Tue, 25 Mar 2008 14:41:31 GMT

    @Robby: Woot! Résumé’d. Glad I could help.

  18. Avatar
    Jake Tue, 25 Mar 2008 15:31:59 GMT

    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?

  19. Avatar
    Peter Cooper Tue, 25 Mar 2008 15:37:27 GMT

    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.

  20. Avatar
    Derek Tue, 25 Mar 2008 16:13:45 GMT

    @Peter: Party pooper. Occam’s Razor party pooper.

  21. Avatar
    Joe Grossberg Tue, 25 Mar 2008 16:59:35 GMT

    +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.

  22. Avatar
    jerome Tue, 25 Mar 2008 17:13:37 GMT

    -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.

  23. Avatar
    Matt Jankowski Tue, 25 Mar 2008 17:29:17 GMT

    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?

  24. Avatar
    Robby Russell Tue, 25 Mar 2008 17:54:35 GMT Recommend me on Working with Rails

    @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]

  25. Avatar
    John Tue, 25 Mar 2008 18:04:04 GMT

    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?

  26. Avatar
    Alice Tue, 25 Mar 2008 18:33:04 GMT

    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.

  27. Avatar
    Reagan Tue, 25 Mar 2008 18:33:22 GMT

    DRY (a)

    Hahaha, I love it!

  28. Avatar
    Reagan Tue, 25 Mar 2008 18:33:23 GMT

    DRY (a)

    Hahaha, I love it!

  29. Avatar
    Jerome Tue, 25 Mar 2008 19:24:13 GMT

    @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
    end
    

    Of 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.

  30. Avatar
    Jerome Tue, 25 Mar 2008 19:26:15 GMT

    BTW sorry if I hurt you; now I owe you a hug.

  31. Avatar
    mef Tue, 25 Mar 2008 21:43:55 GMT

    Seriously… Date.today.year

    For a range? “2006-#{Date.today.year}”

    o_O

  32. Avatar
    Tim Lucas Wed, 26 Mar 2008 15:14:48 GMT

    Here’s a helper I wrote for one of my last projects:

    module CopyrightHelper
      def copyright(year, now=Time.now)
        if now.year == year
          year.to_s
        elsif year / 1000 == now.year / 1000 # same century
          year.to_s + "&ndash;" + now.year.to_s[-2..3]
        else
          year.to_s + "&ndash;" + now.year.to_s
        end
      end
    end
    
    if $0 == __FILE__
      require 'test/unit'
      class CopyrightHelperTest < Test::Unit::TestCase
        include CopyrightHelper
    
        def test_should_return_year_if_copyright_year_is_the_same
          assert_equal "2000", copyright(2000, Time.local(2000))
        end
        def test_should_return_year_range_minus_century_if_the_same_century
          assert_equal "2000&ndash;01", copyright(2000, Time.local(2001))
        end
        def test_should_return_full_year_range_if_different_century
          assert_equal "1999&ndash;2000", copyright(1999, Time.local(2000))
        end
      end
    end

    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)

  33. Avatar
    Raymond Brigleb Thu, 27 Mar 2008 07:13:03 GMT

    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!

  34. Avatar
    Tom Harrison Sun, 30 Mar 2008 16:04:37 GMT

    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 :-)

  35. Avatar
    ROB Mon, 14 Apr 2008 10:23:13 GMT

    Do it a little quicker just by using this in your view:

    <%= Time.now.year %>

  36. Avatar
    Financieel advies Mon, 04 Aug 2008 13:10:26 GMT

    Thanks for the reminder. The Copyright date/year on our web site was no longer current, but now it is!

  37. Avatar
    Facepalm Fri, 06 Mar 2009 18:37:09 GMT

    Very useful files search engine. http://myrapida.com is a search engine designed to search files in various file sharing and uploading sites.

Share your thoughts... (really...I want to hear them)

Comments