Log In

Matt Briggs

"Not all code needs to be a factory, some of it can just be origami." - _why, the lucky stiff

Cool Ruby Tricks

ruby
by Matt Briggs on 06/11/10

So it's been about a month and a half now since I started using ruby and rails professionally. While its been hard work getting up to speed on the domain of contract packaging, while getting up to speed on ruby, and learning vim, it is also just a joy after working with java and c# for so long.

One of the cool things about pair programming is you pick up peoples tricks and styles very quickly. Here is a quick list of some of my favorite ruby and rails tricks I have learned over the last month and a half.

1) Checking if a variable is one of many things

This has been a pet peeve of mine for a long time now.

if (variableName == "option1" || 
    variableName == "option2" || 
    variableName == "option3") 
{ 
  //do stuff 
}

I always felt that was a failure in language design, not even remotely DRY. Awhile back I tried this in ruby, because I knew that the or operator was way more powerful then in c#, but it totally doesn't do what I was hoping

if variable_name == ("option1" || "option2" || "option3")

All that will do is the stuff in the parens will evaluate to "option1", since the boolean value of a string is true. What I was looking for was this

["option1", "option2", "option3"].include? variable_name

A bit nicer version of that would be to use the word array syntax

%w{ option1 option2 option3 }.include? variable_name

2) try, omfg I love you

So in c#, probably a fifth of your code is null checking in some form or another. Things like this are pretty normal

Class2Name obj = Class1Name.DoSomething();
if (obj 
{
    obj.DoSomethingElse();
}

In ruby (with active support), you would do something like this

ModName.do_something.try(:do_something_else)

What that will do, is if do_something returns nil, the call to try will return nil. If it isn't, the try basically works the same way as a send.

This is a prime example of the lisp philosophy, that if you make a language powerful enough, libraries can implement language features.

3) alias_method_chain, just a better way to do it

There is a method called alias_method that takes two symbols, the first being a new method name, the second being an existing method name. What this does is the equivilent of a unix hard link, it will have two method names pointing to the same method. That way you can re=define one of them, and the old one sticks around. We have a concept called 'alias method chaining', where what we want to do is add a pre or post hook to a method that doesn't have one. It usually looks something like this

alias_method :old_foo, :foo
def foo
  puts 'this is redefined'
  old_foo
end

This works great... until the next guy walks in and does the same thing in a different place. Your re=defd foo becomes old_foo, crushing the origional foo. His foo calls your foo, which calls itself, blows the stack, and you have a mysterious stack overflow exception that is exceptionally difficult to debug.

To get around this, rails has a method called alias_method_chain. What this does is takes two arguments, the first is the method, the second is a unique name for what you want to do with the method. alias_method_chain will first alias the method to method_name_without_second_arg. then it will alias the origional method to method_name_with_second_arg that you are responsible for defining. An example would look like this

def foo_with_hack
  puts 'a bit of a safer way to handle things'
  foo_without_hack
end
alias_method_chain :foo, :hack

This has a few benefits. First, since you aren't aliasing the old one to something generic, there is a much lower chance someone will blow it away with their aliasing. Secondly, since you are aliasing your method to something with a unique name, the order of the chaining call has a better chance of staying in tact. Thirdly, it is much more clear what your intention is.

4) Handling an arg that may or may not be an array

Array has a method called flatten. What it does is turns any array into a single dimensional array. Here is an example in irb

irb(main):001:0> [[1, 2, 3], ['a', 'b', 'c']].flatten
=> [1, 2, 3, "a", "b", "c"]
irb(main):002:0> [1, 2, 3].flatten
=> [1, 2, 3]

Pretty cool, right? With a bit of creativity, we can use it like this

def foo bar
  [bar].flatten.each do |b|
    #do stuff
  end
end

So, if bar is an object, wrapping it in square brackets will make it an array, flatten won't do anything, and we iterate once. If bar is an array, wrapping it in square brackets will turn it into an array with a single element, which is the bar array. flatten effectively gets rid of that extra level, then we iterate over it.

my code blog.

what I am reading

Sidebar_clean_code

the people I follow

  • 24 ways
  • ABtests.com - Learn. Share. Improve your conversions today.
  • Ajaxian » Front Page
  • Alex Young
  • BEST IN CLASS
  • briancarper.net (λ)
  • Carbonica Blog Feed
  • Catalog Living
  • Clients From Hell
  • Clojure/core Blog
  • code is code
  • Coding Horror
  • CSS-Tricks
  • Daily Vim: Text Editor Tips, Tricks, Tutorials, and HOWTOs
  • David Chelimsky
  • dean.edwards.name/weblog
  • DHTML Kitchen News
  • disclojure: all things clojure
  • Edge Rails.info
  • End of Line
  • English - AkitaOnRails.com
  • Err the Blog
  • Evil Monkey Labs
  • Extra Cheese
  • Extra Cheese
  • For A Beautiful Web
  • Francis Hwang's site
  • Free Ruby and Rails Screencasts
  • Giles Bowkett
  • Hacker News
  • has_many :bugs, :through => :rails
  • Higgins for President
  • HTML5 Doctor
  • Information Is Beautiful
  • It's an all-you-can-leet buffet !
  • Jay Fields' Thoughts
  • JGUIMONT>COM
  • John Barnette
  • John Resig
  • K. Scott Allen
  • Katz Got Your Tongue?
  • Kirby's Dreamland
  • Kotaku
  • Kotka
  • Lambda the Ultimate - Programming Languages Weblog
  • Lazycoder
  • Loud Thinking by David Heinemeier Hansson
  • LukeW | Writings on Digital Product Strategy and Design
  • mir.aculo.us
  • MongoTips by John Nunemaker
  • Moonbase
  • No Strings Attached
  • Nuby on Rails
  • Official jQuery Blog
  • ones zeros majors and minors
  • opensoul.org by Brandon Keepers
  • Painfully Obvious
  • Painfully Obvious
  • Particletree
  • Paul Irish
  • Perfection kills
  • Plataforma Tecnologia Blog » English
  • Rails on PostgreSQL :
  • Railscasts
  • RedFlagDeals.com - Latest Deals
  • Relaselog | RLSLOG.net
  • remy sharp's b:log
  • Riding Rails - home
  • RightJS News
  • rmurphey
  • Room 101
  • Rubinius Blog
  • Ruby Best Practices
  • Ruby Inside
  • Ruby Quicktips
  • Ruby treats women as objects
  • RubyFlow
  • Signal vs. Noise
  • Slash7 with Amy Hoy - Home
  • Smashing Magazine Feed
  • Snail in a Turtleneck
  • Software Craftsmanship – Katas
  • St. on IT
  • Stevey's Blog Rants
  • Technomancy
  • Tender Lovemaking
  • Test Obsessed
  • Zed Shaw
  • The CSS Ninja
  • The GitHub Blog
  • The MongoDB NoSQL Database Blog
  • The Napkin ~ A Blog By Highgroove Studios
  • The UX Booth
  • The Word of Notch
  • the { buckblogs :here } - Home
  • Thoughts From Eric
  • Uncle Bob's Blog
  • VIM Tips Blog
  • Virtuous Code
  • Web Designer Wall - Design Trends and Tutorials
  • Wow! eBook - Great ebook, great site!
  • #<Mongoid::Criteria:0xbbb2604>
profile for Matt Briggs at Stack Overflow
Feed
atom 1.0

mattcode.net stack

Rightjs
Rails
Mongo
Dropbox