DRY(a): Year After Year
77 comments Latest by Matin Talen Thu, 02 Sep 2010 06:30:08 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">
© 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. ;-)
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
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
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
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
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
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
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
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 %>
Thanks for the reminder. The Copyright date/year on our web site was no longer current, but now it is!
Very useful files search engine. http://myrapida.com is a search engine designed to search files in various file sharing and uploading sites.
christian louboutin sale 激安ブランド腕時計コピー Air Jordan 12 (XII)
Christian Louboutin Sandals sale S級ブランドコピー品 Air Jordan 19 (XIX)
Christian louboutin shoes are high in quality and reasonable in price. It is the best choice for you. It can make you more beautiful and charmful.
http://www.christianlouboutinpub.com">christian louboutin http://www.christianlouboutinpub.com">louboutin shoes <a href=” http://www.christianlouboutinpub.co m”>christian louboutin shoes
It just happened that I found myself looking at yet-another Rails code base this afternoon that was showing 2007 in the footer.
http://www.all-star-shoes.net/ nike outlet http://www.all-star-shoes.net/ all star shoes
Thanks for the reminder. The Copyright date/year on our web site was no longer current, but now it is! http://www.p90xmall.com
This pair of Supra Muska Skytop shoes is made of jean and it will be soft and cool to wear.Supra Shoes is very popular, because of its good quality, novel style and design. It has many styles.
dell xps m1330 Battery dell wr050 Battery
http://www.laptopbatteries-shop.com/acer/aspire-5050.htm pavilion dv8000 laptop Battery[/url]
just happened that I found myself looking at yet-another Rails code base this afternoon that was showing 2007 in the fo
supra mid light grey
argentina 2010 world cup jerseys
The first visit, feel this blog is very goog http://www.the-various.com/
Legally this is pointless, it’s juschi hair straightenert aesthetic. Am I missing something Robby? I mean you talk about it so sternly,ed hardy t shirts using words like ‘guilty’ and ‘offense’…
The Copyright date/year on our web site was no longer current, but now it is!http://www.uk-power-battery.co.uk/panasonic/lumix+dmc-fz30/battery+charger.htm http://www.uk-power-battery.co.uk/panasonic/lumix+dmc-fz30/digital+camera+battery.htm http://www.uk-power-battery.co.uk/panasonic/cga-s007/battery+charger.htm
The hermes handbags may be one of a lot of big-ticket accessories in the world. It can yield three to four crocodiles to accomplish one Hermes Evelyne , the abate of scales on the skin, the amount is college of the hermes scarf . The GREEN ACRES specification includes advanced features, the possibility of viewing different angles of a video stream and simple computations using built-in registers provided by a GREEN ACRES DVD player. The GREEN ACRES DVD COLLECTION mailing list is a good source for further information
Thanks a lot for enjoying this beauty article with me. I am apreciating it very much! Looking forward to another great article. Good luck to the author! all the best!
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.
Demonstrate a unique new conceptjordan shoesAwq01
Thanks for the reminder.
Good luck to the author! all the best!
fashion pandora charms The article written by you very good, I like it very much. I will keep your new article.
MBT
MBT shoes
Louis Vuitton TREVI GM N51998 Louis Vuitton TREVI Louis Vuitton HAMPSTEAD MM N51204 Louis Vuitton HAMPSTEAD Louis Vuitton SALEYA MM N51188 Louis Vuitton SALEYA Louis Vuitton THAMES PM N48180 Louis Vuitton THAMES Louis Vuitton THAMES GM N48181 Louis Vuitton THAMES Louis Vuitton Bloomsbury PM N42251 Louis Vuitton Bloomsbury Louis Vuitton Bloomsbury GM N42250 Louis Vuitton Bloomsbury Louis Vuitton Marais N42240 Louis Vuitton Marais Louis Vuitton Ravello GM N60006 Louis Vuitton Ravello Louis Vuitton SPEEDY 25 N41532 Louis Vuitton SPEEDY 25 Louis Vuitton SPEEDY 30 N41531 Louis Vuitton SPEEDY 30 Louis Vuitton SPEEDY 35 N41523 Louis Vuitton SPEEDY 35 Louis Vuitton Hampstead PM N51205 Louis Vuitton Hampstead Louis Vuitton Saleya PM N51183 Louis Vuitton Saleya Louis Vuitton BERKELEY N52000 Louis Vuitton BERKELEY Louis Vuitton Alma N51131 Louis Vuitton Alma Louis Vuitton Duomo N60008 Louis Vuitton Duomo Louis Vuitton Knightsbridge N51201 Louis Vuitton Knightsbridge Louis Vuitton SAC PLAT N51140 Louis Vuitton SAC PLAT Louis Vuitton Papillon 30 N51303 Louis Vuitton Papillon 30 Louis Vuitton Belem MM N51174 Louis Vuitton Belem Louis Vuitton Highbury N51200 Louis Vuitton Highbury Louis Vuitton Pochette Accessoires N51985 Louis Vuitton Pochette Accessoires
This was a useful post and I think it is rather easy to see from the other comments as well that this post is well written and useful. Keep up the good work Onitsuka Tiger Mexico 66 Gold Black Onitsuka Tiger Mexico 66 Green Beige Onitsuka Tiger Mexico 66 Beige Coffee Onitsuka Tiger Mexico 66 Orange Black
nice post, thank you for your sharing. I hope you can write more so nice post.
nice post.
Wholesale CHANEL Bikinis Wholesale JUICY Bikinis Wholesale Tous Bikinis Wholesale GUCCI Bikinis Wholesale Women’s shirts Wholesale Women’s sweaters Wholesale Women’s Jeans Wholesale Women’s trousers
http://www.winbatterycharger.com/samsung-smx-f30-battery-charger-imhn.htm”>samsung smx-f30 battery charger. Discount samsung smx-f30 battery charger. We offer best battery charger for samsung smx-f30 with Fast delivery
If you want to make China Wholesale someone happy you have to Wholesale tiffany learn to appreciate them more. Give credits to the accomplishments coach handbags one makes—no matter how ED hardy jeans little—and give importance to the efforts they’ve made. People need to be appreciated one way nike shoes or another, and by being generously True Religion jeans appreciative, you are sure to extend happiness to someone.
Aw, this was a really great post.
China Wholesale Wholesale tiffany coach handbags ED hardy jeans nike shoes True Religion jeans
China Wholesale Wholesale tiffany coach handbags ED hardy jeans nike shoes True Religion jeans
If you want to make China Wholesale someone happy you have to Wholesale tiffany learn to appreciate them more. Give credits to the accomplishments coach handbags one makes—no matter how ED hardy jeans little—and give importance to the efforts they’ve made. People need to be appreciated one way nike shoes or another, and by being generously True Religion jeans appreciative, you are sure to extend happiness to someone.
The price also play Wholesale[/url] an important role in shopping. [url=http://www.worthmall.com/]Wholesale tiffany[/url] one of her favourite songs, Coco. She [url=http://www.worthmall.com/]coach handbags[/url] was nearly 20 when she caugh [url=http://www.worthmall.com/]ED hardy jeans[/url] the eye of a dashing . First of all, do not hurry when buying, matter of fashion style. It is advisable the [url=http://www.worthmall.com/]nike shoes[/url] online shop. You can even refer to magazines and fashion to [url=http://www.worthmall.com/]True Religion jeans[/url] know what type of are in fashion. For instance, women
welcome to http://www.worthmall.com. there is many kind of goods for you to choose, such as clothes, shoes, watches, bracelet and so on. there is various items to choose from. thanks for your support. have a good day.
your artical is very interesting, and i also have a brilliant website to share with you. http://www.worthmall.com . thanks. you won’t be a loss to visit it. maybe you can get something you are favorite.
nikon coolpix s2 charger replacement charger
Air Jordan Shoes
Welcome to our company, we supply many styles of clothes, shoes and handbags, hats, sunglasses, belts, jewelries and so on. Hope you can like them.
ter a few months has passed) that your Copyright date/year on your web site was no lon
I was very pleased to find this site.wholesale jordan shoesI wanted to thank you for this great read I definitely enjoying every little bit of it and I have you bookmarked to check out new stuff you post. and wellcome to my web wholesale handbags,we supplier all kinds of jordan shoes and coach handbags and all colors for choice.
Thousands of mbt are sold everyday, including MBT Ema and MBT Sandals,everyone give high pirze to them.
Hey this is a great post. Custom Blankets,I’m going to email this to my buddies.Fleece Blankets,I will return to check on upcoming articles thanks for sharing.Plush Blankets,I would be extremely interested to hear more information on this.Embroidered Blankets, Cheers!Amiable dispatch and this mail helped me alot in my college assignement.fleece throw,Just want to say what a great blog you got here! Say thank you you on your information.Keep posting stuff like this i really like it.
m40372 Louis Vuitton Neo louis vuitton verona gm louis vuitton laptop sleeve louis vuitton speedy 35 lv speedy 35 verona mm lv verona mm louis vuitton beaubourg louis vuitton citadin lv purses louis vuitton speedy 30 damier ebene louis vuitton insolite wallet louis vuitton mini citadin lv josephine louis vuitton romance thames gm louis vuitton alma louis vuitton speedy louis vuitton speedy 25 louis vuitton papillon lv wallets louis vuitton epi lv speedy 30 lv epi leather louis vuitton sistina pm louis vuitton verona pm musette louis vuitton papillon lv louis vuitton zippy louis vuitton keepall louis vuitton laptop louis vuitton solar pm louis vuitton mahina leather
lv cosmic blossom cosmic blossom louis vuitton cosmic blossom lv store lv purses Soft Briefcase batignolles horizontal louis vuitton galliera lv louis vuitton damier azur handbag louis vuitton damier speedy 30 louis vuitton florin louis vuitton damier neverfull mm bulles louis vuitton vavin louis vuitton zippy wallet louis vuitton laptop laptop sleeve 13 louis vuitton boetie gm louis vuitton epi leather epi leather louis vuitton anton Sac Bosphore
coach bags Canada http://www.coach-tote.com/ vibram five fingers http://www.vibram-toe-shoes.com/ Masai Shoes http://www.masai-barefoot.com/ MBT UK http://www.mbtfeet.com/
Gucci Cosmetic Case 145750 F4DYG 9773 Gucci Cosmetic Case 153228 AA61G 5709 Gucci Cosmetic Case 153228 AA61G 9022 Gucci Cosmetic Case 153228 FN92G 9752 Gucci Cosmetic Case 212122 FFPAG 9761 Gucci Cosmetic Case 224093 FFKPG 9765 Gucci Cosmetic Case 245959 FJ72R 1000 Gucci Large Cosmetic Case 224089 FJ72R 1000 Gucci Large Cosmetic Case 224091 FJ72R 4506 Gucci Large Cosmetic Case 29595R F40IR 9643 Gucci Medium Cosmetic Case 224090 FJ72R 1000 Gucci Medium Cosmetic Case 224090 FJ72R 4506 Gucci Small Cosmetic Case 29596R F40IR 9643 Gucci Carry-on Duffel 201479 FCIZG 8501 Gucci Carry-on Duffel 232602 A7M0Z 9014 Gucci Carry-on Duffel 232772 FP43N 9080 Gucci Duffel 245075 F0G3Y 9860 Gucci Duffel 246386 F567N 1060 Gucci Large Carry-on Duffel 206500 AIZ1G 2044 Gucci Large Carry-on Duffel 206500 BEG1G 2145 Gucci Large Carry-on Duffel 206500 FCIEG 9643 Gucci Large Carry-on Duffel 233050 F4F5R 9791 Gucci Large Collapsible Carry-on Duffel 146310 F4F5R 1060 Gucci Large Collapsible Carry-on Duffel 146310 F4F5R 9791 Gucci Medium Carry-on Duffel 206501 FCIEG 9643 Gucci Medium Carry-on Duffel 246454 FCIGG 8588 Gucci Medium Duffel 201539 BEG1G 2145 Gucci Medium Duffel 245072 FN61Y 9643