Simplifying Your Ruby Code
I used to write Ruby code like this a lot when I my brain was still half .NET.
def is_ready?
if self.status > 3
return true
else
return false
end
end
I see this all the time on the Rails mailing list. Would you be surprised to know that you can write the same method this way:
def ready?
self.status > 3
end
(I’d do away the the magic number “3” in favor of a constant, but I digress…)
Notice two things:
- Methods that return a true/false indicator should end with a question mark. For more on this topic, see my other post on the topic of naming conventions in Ruby.
- Ruby uses the last-evaluated expression as the return value. No need to wrap it with a useless if/else block.
Questions? Got another example of code patterns you’ve seen that could be simpler? Use Textile formatting in the comments.
Yes, Ruby 1.9 Is Available, But Beware 4
You may already know by now that a new version of Ruby, 1.9, has been announced as being available for download. However, if you’re not familiar with Ruby’s tradition, you might think that you should start upgrading all of your production servers today.
Do not do that.
Although Matz indicated in his announcement that 1.9 is a development release, Dave explains what this means. It is not a stable production release.
Ruby has a tradition of using odd-numbered releases for experimentation and development, and even-numbered releases for widespread public adoption. 1.9 has many cool things, and some subtle but significant changes to the Ruby language, so by all means download it, play with it, learn it, love it.
I just hope that by next Christmas we’ll all be downloading – and installing – 2.0.
Ruby 201: Using call stack information at runtime 5
This is just a quick tip that you may never need but came in very handy for me this week.
While perusing the log of one of my Rails apps, I noticed that a certain method of one of my models was being called four times when I expected it to only be called once. I did the usual Find in Files to see where I'm calling it, but that didn't really answer the question. A mental walkthough of my code didn't reveal why this method was getting called more than once.
I'm actually at home while I write this, and I can't remember the exact code, but it went something like this:
def something_important
RAILS_DEFAULT_LOGGER.info "About to do something important"
if something_exists?
do_expensive_operation
end
end
I found a test which was already exercising code which called this method, and sure enough, when I ran that one test, I got multiple log statements emitted into the test log file.
During testing, I tend to use puts statements when I want to see some debug output (although tailing the log file would work too). So I did this:
def something_important
puts caller.grep(/\/app\//).first
RAILS_DEFAULT_LOGGER.info "About to do something important"
if something_exists?
do_expensive_operation
end
end
And presto, when I ran the test, it displayed for me the exact line that was calling this method each time. That revealed the source of the problem, which was easily fixed. In this case, seeing the actual call stack was really helpful.
caller is not Rails magic; it's a Ruby method of the Kernel class, which all objects inherit. It returns an array of strings representing the call stack. Now, in a Rails application, the call stack can be really long. In my case, the 15 or so methods at the top of the stack were coming from the Rails framework itself, so that was a lot of noise to weed through.
By doing a grep on the array and choosing the first match, I filtered out everything up until the first entry in the call stack that was coming from a file in the app folder or below. In other words, this revealed the most recent line in my code that triggered this method.
Ruby 101: Naming Conventions 28
UPDATE: Fixed some typos in the DialUpModem example code.
Ruby enforces certain coding conventions, while others are considered to be community-accepted idiomatic Ruby. I’d like to cover them here.
I can’t cover everything in one blog post. Instead, I’ll review the more egregious cases that seem to pop up on the Ruby and Rails mailing lists. Most of these seem to come from our Java friends who are now using Ruby without regard to learning Ruby style. .NET developers are prone to the same criminal activities, so I hope this will help both Java and .NET developers that are new to Rails.
Today all of these situations involve method names.
lowercase_and_underscored
Suppose we have a class DialUpModem with a method that will terminate the connection.
Please don’t do this, you formerly-Java people:
def hangUp()
nor this, formerly-.NET people:
def HangUp()
Instead, do this, all you seen-the-light-and-now-very-cool people:
def hang_up
Notice two things here:
- everything is in lowercase
- underscores separate words
- don’t append empty parentheses if there are no parameters
Ok, that was three things, not two, just to see if you’re awake.
Methods that return boolean values
Don’t do this, formerly-Java people:
def isOnline()
nor this, formerly-.NET people:
def IsOnline()
Instead, do this, all you seen-the-light-and-now-very-cool people:
def online?
See? We don’t use the word “is” to start a method name. Instead, the Ruby language recommends that you use a question mark at the end of a method name to indicate that it will return a boolean value. (It’s not required by the language, it’s just a convention you should follow.)
By the way, you can still take parameters if you need to:
def high_speed?(min_speed = 19200)
Properties Are For Monopoly Players
...not Ruby programmers. So puleeeze don’t do this:
class DialUpModem
def get_speed
return @speed
end
def set_speed(value)
@speed = value
end
end
Don’t use getters and setters when there’s no logic involved. Do this:
class DialUpModem
attr_accessor :speed
end
Done. Nice. Clean. Simple.
If you do have logic involved, you can still override the getter or setter as appropriate:
class DialUpModem
attr_accessor :speed
def speed=(value)
# Limit the speed to 19200 baud.
if new_speed > 19200
@speed = 19200
else
@speed = value
end
end
end
Notice the ’=’ sign at the end of the method name – that’s how you define a “setter” method in Ruby.
If/Else Statements Are Suspicious
I know I said this post was just about method names, but now that you’ve made it this far I can’t resist one more Ruby tip.
See that setter method we just wrote? That is some very, very ugly Ruby code.
Learn instead to wield the power of the Enumerable module:
def speed=(value)
@speed = [value, 19200].min
end
How to Learn Idiomatic Ruby
Read the good Ruby books by the good authors: David A. Black, Dave Thomas, Hal Fulton, and others. And read as much Ruby code as you can, so you can start to become assimilated into the Ruby style of programming.
Ruby.NET and IronRuby are open-sourced 8
As Dr. Nic recently pointed out, the Ruby.NET project is now open source. Ruby.NET was (is?) funded by Microsoft, but later they seem to have taken a different direction with IronRuby, which is also now an open source project.
Of course, IronRuby uses Microsoft's license instead of something most open source developers are familiar with, like the MIT license or one of the other major licenses. MIcrosoft's license is short, easy to read, and makes sense. But I wonder why they couldn't just adopt one of other standard licenses. (Wait, I forgot, we're talking about Microsoft here...) And just because a project is "open source" doesn't mean it's good, and it doesn't mean that MIcrosoft can't have tremendous influence over the IronRuby project.
In fact, I wonder why Microsoft is starting to do more open-source-like things. Is it just an attempt to improve their perception? Or is it a real attempt to embark upon a new direction for a given segment of their development toolset? John Lam has responded often to similar questions posed on Ruby and Rails mailing lists, and I've always been impressed by his candor and his confidence in the direction that his team is heading.
But for me, Microsoft's lack of support for Ruby.NET actually makes it more interesting to follow than the IronRuby project. Even though it now appears obvious IronRuby, and not Ruby.NET, is destined to become the de facto Ruby implementation for Visual Studio and Silverlight. Perhaps if I find some spare cycles (and if I feel like working in .NET again... which is a big question mark), I'll try to lend a hand to the Ruby.NET cause.
If you're a .NET developer with an interest in seeing Ruby flourish on the DLR, then you should step up to the plate and contribute to one or both of these projects.
(If John Lam or Wayne Kelly are reading this, your input and perspective would be welcome.)
Ruby 101: The Mysterious Dr. Nil
Photo credit: http://www.flickr.com/photos/biczzz/365774667/
UPDATE: Thanks goes to Dan for pointing out my Java mistake.
Zilch, nada, nothing
Many programming languages have a keyword to mean that a variable holds “no value.”
- When I first learned C, I thought
NULLwas a keyword at first; later I learned it was justdefine‘d to be 0 - C# has the
nullkeyword - Java has
null - VB uses the keyword
Nothing - SQL uses
NULL.
Ruby also has a way to represent the same concept with the keyword nil:
my_var = nil
In Ruby, there are several ways to find out of a variable has the nil value. First, there’s the obvious:
if my_var == nil
puts "It's nil!"
end
This is most similar to how you would check in other languages. But there is another way, too.
if my_var.nil?
puts "It's nil!"
end
If you’re new to Ruby, the above if statement should make your head turn just a bit. If my_var is nil, how can we call a method on it? In C#, calling a method on a null reference would throw an exception. Yet, here we are, calling a method on an object that’s nil.
Get Out The Magnifying Glass
Let’s look more closely at the nil? method. It’s available on every Ruby object. Open up an irb session:
1.nil?
=> false
"hello".nil?
=> false
my_var.nil?
=> true
So everything can test itself to find out if it’s nil. To understand how we can call a method like nil? on an object that itself is nil, let’s be more precise: we’re sending the message “nil?” to the my_var object. In order for this to work, my_var must refer to an actual object taking up actual memory. In C#, doing something like my_var = null makes my_var point to nowhere. It will not refer to any object at all. But in Ruby, when we say:
my_var = nil
we are definitely not saying that my_var does not refer to anything. In fact, my_var still refers to a valid object at a valid memory location! What’s more, it’s an object that can respond to messages, including the “nil?” message. Strange, right?
Well, if my_var really is a real reference to a real object, exactly what object is it referring to?
It’s Just Another Object
It turns out that the nil keyword in Ruby evaluates to a predefined global object. (I can’t bring myself to say “global variables” because global variables are evil, right?) You know how in Ruby, we like to say that everything is an object? nil is no exception! Behold:
nil.class
=> NilClass
nil.object_id
=> 4
Awesome! We’ve proven that nil is a real object, having a class and object_id just like any other object. There’s really no magic at all behind the statement:
my_var = nil
Now we can see, all we’re doing is assigning my_var to refer to the one and only nil object. It’s exactly no different from any other assignment statement in Ruby: your variable just happens to refer to the global object nil, no more and no less.
However, the language does give special treatment to the nil object in certain sitations, like if statements. if knows to evaluate to false if the given expression refers to nil:
if my_var
puts "It's not nil!"
end
Here, the puts statement will not execute if my_var is false, or if my_var refers to the global nil object. This special treatment is necessary, because normally any non-nil object reference will evaluate to true:
my_var = Array.new
if my_var
puts "It's not nil!"
end
This time, the puts will execute and display the string It’s not nil!. In Ruby, anything that’s not false and is not nil evaluates to true. Since my_var refers to an Array object, it is not false nor does it refer to nil, and so the condition evaluates to true.
That’s a brief look at the mysterious nil in Ruby. Questions or comments? Drop me a comment below.
Ruby 201: Weird Hash Syntax 7
You know how I normally rave about Ruby’s clear and natural syntax, how I prefer it over languages like C#, and generally say that Ruby is better than a baked loaf of dough cut into thin vertical strips.
But today… not so much.
Hash#select Returns… An Array?
Yes, Hash#select returns an array. I’m not sure why. I’m sure it seemed like a good idea at the time. But the other day I needed to get a “subset” of a Hash, and since Hash includes Enumerable, I thought I could do a select and get back the key-value pairs that I wanted. But, it returned a bunch of nested arrays instead.
vehicles = { :cars => 36, :boats => 8, :trains => 12, :planes => 21 }
vehicles.select { |k,v| v > 20 }
=> [[ :planes, 21], [ :cars, 36]]
Fortunately, it’s easy to turn this back into a hash. Hash overrides the class-level [ ] operator in an interesting way. If you pass it a flat list of values, it will construct a hash by assuming that the list is an alternating list of keys and values:
Hash[:apple, 'red', :banana, 'yellow']
=> { :apple=>"red", :banana=>"yellow"}
So back to the original problem: can we somehow turn [[:planes, 21], [:cars, 36]] into a flat list?
First, we “flatten” the array, which gets rid of all nested levels of the array:
a = [[:planes, 21], [:cars, 36]].flatten
=> [ :planes, 21, :cars, 36]
Close, but we still have an array, and we need a simple list of values instead.
Splat to the Rescue
We now use the Splat operator and use the Hash#[ ] class-level method to create our new hash:
h = Hash[*a]
=> { :planes=>21, :cars=>36}
Ta da!
Make It Part of Ruby
If you do this a lot, you could wrap this up in a method… but you can also choose to modify the Hash class directly:
class Hash
alias :old_select :select
def select(&block)
a = old_select(&block)
Hash[*a.flatten]
end
end
Behold, our original code now does something beautiful:
vehicles.select { |k,v| v > 20 }
=> { :planes=>21, :cars=>36}
Wow, 7 lines of code and I’ve just made Ruby bend to my will. In fact, it turns out the next version of Ruby will support this syntax directly.
You know, there are some days when I just have to say, I think Ruby is better than sliced….
Ruby 101: Hashes are Cool
Of all the data structures in Ruby, the Hash is probably the most famous, especially when it comes to Rails programming. Ruby syntax is well-suited to hash containers, making the hash easy to use for experienced Rubyists, and, well, not so easy to use for those new to Ruby. And those who are new to Rails are almost always new to Ruby as well. As a result, the onslaught of hashes in Rails is one of the first hurdles that every Rails developer must jump over if they want to get past the “newbie” stage and into the “developer” stage.
One of the first exposures a new Rails developer has to hashes is when a line like this is seen in a book (or in the Rails documention, in this case):
has_many :people, :class_name => "Person", :conditions => "deleted = 0", :order => "name"
When I first started seeing Rails code like this, I loved it. It was obvious what it meant – this object will be related to many people, represented by the class Person, but only for those who are not deleted, and we will see them sorted by name.
But what was the Ruby syntax doing? And how in the world could I have known to write code like this? I had no clue, and I certainly had no idea that a Hash was being used in that code. No way.
No Cheech and Chong jokes, I promise
Let’s step back for a second. Hopefully, this code is already understandable to you:
faves = {}
faves['color'] = 'purple'
faves['sport'] = 'hockey'
faves['framework'] = 'rails'
Here we create an empty hash, then populate it with key-value pairs one at a time.
The hash can actually be a heterogeneous structure if you want – you can use any type of key and any type of value in the same hash structure:
faves[:color] = 'purple'
faves[1] = Hockey.new
Here I’ve used a symbol and an integer as keys, and a string and an object as values.
In Rails hashes, you’ll find that symbols are the preferred key data type of choice instead of strings. Symbols are more eco-friendly than strings (less memory consumption and less garbage collection) when you need a human-readable identifier without any of the string manipulation features.
Hashes used as function arguments
The real interesting use of a hash is as a function argument. Let’s look at how I used to write a function in C# – I’m sure you can think of a similar equivalent in your previous language of choice.
public void SetFile(String filename, Int32 linesToRead)
This code uses positional parameters. The calling code needs to pass its arguments in the exact order as declared by the Initialize function, or it’s not going to work. This is one reason why statically typed languages were thought to be helpful, because if the calling code pased an integer followed by a string, the compiler would catch it (this was back in the stone age of programming, before unit testing was widely understood).
The problem came when I wanted the client to supply another argument. I had to either write another overloaded version of the Initialize function that took the extra parameter, or change the existing code and make existing clients break until they fixed their code as well:
public void SetFile(bool openNow, String filename, Int32 linesToRead)
Ruby also can take positional parameters, so you face the same dilemma in Ruby as well. Actually it’s a bit worse in Ruby, since method overloading isn’t supported. So if you need to change a method’s parameters, you’re stuck with either breaking existing client code, or adding another method to your class. Not good.
Enter stage right, the hash. Suppose I ask my client to pass a hash of values all at once, instead of passing them one at a time:
def set_file(options)
if options[:open_now]
# open the file
end
# etc.
end
# The client code...
options = {}
options[:open_now] = true
options[:filename] = 'jeff.txt'
options[:lines_to_read] = 50
set_file(options)
Here the client code passes in a hash, where the parameters are passed by providing key/value pairs. The client doesn’t have to worry about what order to pass arguments anymore. But it now has a different burden, which is that valid hash keys must be used in order for the function to operate correctly.
So where’s the win?
Ruby 934, C# 0
Ok, I haven’t really kept score for the past 10 months… but here again Ruby wins out. First, realize that my demonstration of populating a hash is just about the most cumbersome way possible in Ruby. Here’s a more typical way you create a hash with a few key/value pairs in it:
options = { :open_now => true, :filename => 'jeff.txt', :lines_to_read => 50 }
Beautiful. One line, easy to read. Now the client code looks like this:
# The client code...
options = { :open_now => true, :filename => 'jeff.txt', :lines_to_read => 50 }
set_file(options)
Good Ruby programmer that you are, you might be tempted to get this into one line and factor away the temporary variable:
# The client code...
set_file({ :open_now => true, :filename => 'jeff.txt', :lines_to_read => 50 })
Now, it’s a matter of taste, but in these situations I like to take advantage of the fact that Ruby usually doesn’t require parentheses:
# The client code...
set_file { :open_now => true, :filename => 'jeff.txt', :lines_to_read => 50 }
Not bad. Very readable, right? You can practically just read it left to right like English.
Actually, it’s terrible – those curly braces are driving me crazy! I want perfection! But we can’t get rid of them. Those braces are what tells Ruby that we’re creating a Hash.
Or can we? It turns out, if the last parameter you are supplying is a hash, then you can actually omit the curly braces! Ruby will automatically collect up your comma-delimited list of key/value pairs into a hash for you.
set_file :open_now => true, :filename => 'jeff.txt', :lines_to_read => 50
Ahhhh. Beatiful, easy to read code.
So let’s go back to the has_many example I started with.
has_many :people, :class_name => "Person", :conditions => "deleted = 0", :order => "name"
We can see now that we’re calling a method named has_many, and we’re passing it two arguments. The first is :people. The second is a hash, containing the keys :class_name, :conditions, and order. Internally, the Rails code looks for these keys in your hash, and acts according to the values you’ve stored there.
Even better, future version of Rails can add features to this method by simply documenting which new key/value pairs are supported. Existing client code won’t break and the Rails API wont’t have to get another new method.
Using hashes instead of positional parameters is one way the Rails codebase has avoided code bloat, in spite of the number of releases it’s enjoyed so far.
Ready to learn more about the synergies between Ruby and Rails? Sign up now for our two-day Ruby on Rails workshop Essential Rails before it’s too late.
Ruby 101: Methods and messages
I hope that someone gets my
I hope that someone gets my
I hope that someone gets my
Message in a bottle
– The Police
Got a great question from Scott Porad the other day, asking about this line of code that’s produced by the scaffold generator in Rails 1.2 (note, in Scott’s application, his model is called content):
My question has to do with this line:
<td ><%= h content.send(column.name) %></ td>
What exactly is content.send(column.name) doing?
We all know that Ruby is an object-oriented language. However, many of us who are accustomed to .NET or Java may not realize that Ruby is really based on message passing, not method calling. The difference is so subtle that you can start using Ruby right away, and get pretty far, without ever knowing the difference. But this line in the scaffold code takes advantage of message passing to great effect.
When you write a Ruby class and define some methods inside of it, those methods are just predefined responses to certain messages.
class Thermometer
def temperature
75
end
end
To think in terms of message passing instead of methods, try to read this code out loud as, “This is class Thermometer. It can respond to a message named ‘temperature’. It will respond with 75 when it receives the message.”
It looks like a method call in your previous favorite language, and the message-calling syntax in Ruby looks like the method-calling syntax in that old language, too:
t = Thermometer.new
puts "It is " + t.temperature " + degrees outside."
When the Ruby interpreter sees t.temperature, it passes the message temperature to the t object. There are actually two ways we could have sent this message to the object. The first is what we did here. But there’s another, more generic way to send a message to an object, and that’s with the send method that’s available to every Ruby object:
t = Thermometer.new
puts "It is " + t.send('temperature') " degrees outside."
Here we sent the message named ‘temperature’ to the object. Since Thermometer has defined a response to the temperature message, Ruby is able to locate that response and execute it.
This means that you can write code that does not know method names a priori. Let’s go back to the scaffold code. When you run script/generate scaffold Product, the generator has no idea what columns your Product table will have. Yet it is able to generate that code that will automatically display all of the data in your table. It’s able to do this by first reflecting on your table for the column names, and then asking your model for the value of the attribute with that same name:
product.send(column.name)
So in this code, the product object is being passed a message, and it’s using the column name as the name of the message. ActiveRecord responds by returning the value of that column in the database. Beautiful!
In fact, your code can first find out if a given object will respond to a given message with respond_to?:
t = Thermometer.new
if t.respond_to? 'temperature'
puts "Yes, it can tell you the temperature"
else
puts "No, it can not tell you the temperature"
end
Today we looked at one way an object can respond to this message: providing a predefined response to a specific, named message. There’s another way to respond to messages, without writing def blocks at all.
But as Alton Brown likes to say, that’s another show.
Questions? Clear as mud? Drop me a comment.Ready to learn more? Sign up now for Essential Rails
Script/console tip for the lazy 12
I use script/console a lot. It's a great way to learn about the Rails API, inspect objects, and get really good with ActiveRecord subtleties.
Yesterday I was doing this in script/console:
>> Product.find :all, :order => 'title asc'
=> [#<Product:0x342ee58 @attributes={"title"=>"Another", "id"=>"2", "released"=>nil, "version_number"=>"1.0"}>,
#<Product:0x342ee1c @attributes={"title"=>"My Product", "id"=>"1", "released"=>nil, "version_number"=>"1.5"}>]
Good, there's a couple of products in my development database to play with. I wanted to get all of the titles in an array, sorted in ascending order. So I need to take the results of my previous statement and call collect on it - so I was about to do this:
>> Product.find(:all, :order => 'title asc').collect { |product| product.title }
With irb history installed, I can just hit my up-arrow to recall the previous statement. But I'd still have to edit it, to insert the parentheses, before I could append the collect iteration code. So what does a lazy person do when confronted with a task that might take a second or two? Why, spend a lot more time googling for a better solution, of course.
Sure enough, after a few minutes with my good friend Google, I found it:
>> _.collect { |product| product.title }
Yes, that's an underscore character in front of the .collect. In irb (and hence, script/console), an underscore is a kind of global variable that holds the last result. So in my case, it represents the collection that I had just found. You can also capture it in a variable if you want:
>> products = _
>> products.size
=> 2
Just a tip for anyone out there that's just as lazy as me.
Ready to learn more? Sign up now for Essential Rails
Ruby and .NET getting closer together 1
I know there's a been a lot of talk about about Microsoft's work-in-progress "DLR", especially with respect to the Silverlight project, but I wanted to also highlight some cool things the SapphireSteel guys are doing. In addition to their excellent Visual Studio Add-In, they're also continuing to blur the boundary between .NET and Ruby and you can do it today, without the DLR.
Cool stuff, guys. Keep it up.
Review of Hal Fulton's The Ruby Way 16

Disclaimer: I received a complimentary copy of The Ruby Way back in January. I was never asked to write a review. I decided to blog about it because after six months it continues to help me do my work. I now routinely recommend this book people to people I know.
Brian and I like to say that if you really want to get good at Rails, you have to get good at Ruby. The question becomes, how do you get good at Ruby? You write code, you read other people's code, and you read books. And maybe the occasional blog :-)
Back in January I got a copy of The Ruby Way, 2nd Edition by Hal Fulton. I was intending to write a review of it back then, but we were in the last moments of preparing for our Web Developer Makeover class. And I've been behind ever since. So today I finally start catching up.
If you see this book at a bookstore, you might be intimidated by how thick it is. Now, I generally find that the quality of a technical book is inversely proportional to its thickness. I remember back when I was just switching from C++ to C#, there were lots of C# books that were at least two inches thick. They looked impressive from the outside. But flipping through them in the bookstore revealed a ton of full-code printouts and screenshots of every single stupid step of every Visual Studio Wizard you could run. Publishers need a certain page count to justify their prices, I guess.
So you can imagine my mild amazement when I read the Ruby Way, a two-inch thick book, that has no filler whatsoever. I mean none. This book is 700 pages of true Ruby goodness. If you want to start getting your mind to think in Ruby, you can't go wrong with this book.
I'm not even going to try to cover everything in the book, but let me summarize why The Ruby Way will be on my bookshelf for a long time.
First, the overall writing style is awesome. I find Hal's style to be very readable and easy to follow.
Second, I have learned at least one new thing from every section I've read. Whether you're a new Rails developer or you've been using Ruby for a year or two already, you will definitely learn something from every chapter.
Third, this book does not try to be all things to all people. Early on he states that this book is not a reference manual nor a beginniner's guide to the language, instead citing other sources like the PickAxe for that sort of thing. What a refreshing thing for an author to say! Most programming books feel obligated to include a few "introduction to Ruby" chapters to appeal to a wider audience and/or just inflate the page count some more. This alone makes me much more likely to recommend this book to others, since I know that their money is not being spent on a duplication of the PickAxe.
I used to say there are only two must-have books for Rails professionals: the PickAxe and AWDwR.
But now I say three.
Ruby 101: Transparent Code 22

Photo credit: http://flickr.com/photos/worldofoddy/
One of the reasons I love Ruby is that my code often reads like English. When my code becomes as readable as an English sentence, I find it more likely that I'll code exactly what I want to achieve. Code is easier to understand and maintain when the original intention of the code is self-evident. I think that's partly why Java and C# were so attractive as compared to C++. And why C++ was so much more fun than C.
Ruby is a large language, just like Chicago is a big city. But today I'd like us to venture down a side street, to take a road less traveled by Ruby newcomers. We will learn how to use the modifier form of some well-known Ruby keywords to improve your code's clarity.
Say Cheese
Let's say we're writing code to operate a digital camera. You've got methods like capture_image, for example, which will capture an image from the sensor array and generate an image file onto the memory card (and if we're lucky, emit a silly "click" sound to imitate an analog camera). Let's look at how you might write the code for when the user presses the shutter button:
def shutter_clicked
if @camera.off? || @camera.memory_card_full?
return
end
capture_image
end
So if the camera is off or we're out of memory, we just bail. If all is good, we take the picture. This was my style when I started with Ruby, and if that code looks like how you would do it too, then you're in for something new and rewarding.
The key is to know that keywords like return, while, if, unless, and until can be used as modifiers. This means that you put the conditional part after the keyword. Sounds silly, and sometimes it is. But sometimes it has a big payoff.
The code we wrote was trying to capture some requirements. In order to take a picture, the camera can't be off and the memory card can't be full. Using the modifier form of return, you can rewrite the above code like this:
def shutter_clicked
return if @camera.off? || @camera.memory_card_full?
capture_image
end
The first line says, return right away if the camera is off or the memory card is full. If we get as far as the second line, we can go ahead and capture the image. Read the code out loud. Sounds better, right?
But wait, you can go a step further. For example, you might prefer this:
def shutter_clicked
capture_image unless @camera.off? || @camera.memory_card_full?
end
Now read it out load again (under your breath if you're in a small cubicle). This expresses the intention a bit differently. When read aloud, the first thing we hear is "capture image". I find it helpful to hear that first, because that's what happens 90% of the time when the shutter is clicked. By writing the code this way, we emphasize the expected behavior. We use the unless clause to guard the behavior with our business rules. The code is more transparent, making the requirements easier to see. This code is easier to understand and maintain.
But let's go back to the original code for a minute. There's no right or wrong way to do this, and perhaps you didn't like my original example in the first place. After all, it's got the awkward-looking return statement hanging out in space. By flipping the logical operator around, the original code could have looked like this:
def shutter_clicked
if @camera.on? && @camera.memory_available?
capture_image
end
end
This reads better already. But we still have the if-then feeling in there. Sounds more like code, and less like English. How about this?
def shutter_clicked
capture_image if @camera.on? && @camera.memory_available?
end
Either way, it's up to you. I wrote Ruby code the "old way" for a long time, and it's only in the last six months or so that I've switched to the modifer forms. Just use the form that seems more natural to you.
Like It's 1999
Now suppose you get a new requirement that the camera should have a feature to take pictures non-stop in strobe-like fashion until every byte of memory is used up. (You ask your customer, why, oh why would anyone want this feature, but it's a "show-stopper" requirement, a "must-have", a feature that the camera "absolutely cannot ship without". So you press on.)
It actually turns out to be an easy method to write:
def go_crazy
while (@camera.memory_available?)
capture_image
end
end
Again - you've been writing code like this for a long time, and especially if you're coming from VB.NET or C# or Java, this code probably seems perfectly readable to you.
Your problem is that you've been in the dungeon so long, you believe that the torch on the wall provides enough light. What if you could escape to the outside and see the sun? Behold:
def go_crazy
capture_image until @camera.memory_card_full?
end
or if you prefer,
def go_crazy
capture_image while @camera.memory_available?
end
Just Do it
The modifier forms aren't just niceties or afterthoughts in the language. They are there for good reason. Try them for a while and see if it doesn't improve your style. Use them whenever and wherever it seems appropriate to you. Make the intention of your code clear and obvious.
Ruby 101 for .NET Developers: Select or Reject? 0
How can we be in
If there is no outside
Peter Gabriel, "Not One of Us"
Just a quick post today about a method I don't use every day, but sure comes in handy when I need it: reject.
There are actually a handful of different Ruby classes that provide a reject and/or reject! method, but I only care about Array and Hash, since those are the ones I use most often in Rails coding.
Sometimes you will have a collection of things, and for some reason you want a subset of that collection. A common way is to use the select method, because it takes a block in which you can tell it which things belong in your subset:
sports = ["Hockey", "Baseball", "Basketball", "Football"]
popular_usa_sports = sports.select { |sport| sport =~ /^(B|F)/ }
But sometimes it's easier think of your subset by what you don't want instead. For that, use reject instead of select:
sports = ["Hockey", "Baseball", "Basketball", "Football"]
popular_usa_sports = sports.reject { |sport| sport == "Hockey" }
Same concept works for hashes as well as arrays. I find that my code can sometimes become more readable this way.
There's also a reject! method which will modify your collection, and the rejected elements are gone forever (hence the exclamation point).
Ruby 101 for .NET Developers: Use blocks to help you refactor 5
As I've learned more about blocks in Ruby, I've had more fun refactoring my code. I first learned about refactoring from Martin Fowler's excellent book about six years ago when I was doing C++ programming for a living. Although the examples were in Java, it was very readable, and that was my first nudge down the agile path. I then started to understand what unit tests were all about, because I could refactor if I already had unit tests written... and then it was on to extreme programming... and the rest is history.
But back to refactoring... I loved refactoring in C#. My refactoring mainly consisted of just breaking up long methods into shorter ones. Once in a while I would create a new class out of a bunch of methods if I felt the existing class was getting too many responsibilities (in other words, more than one :-). But mainly, I was just cutting and pasting code into new methods, to keep each method short and as high-level-looking as possible.
In Ruby, I pretty much do the same thing, but utilizing blocks gives me a weapon I didn't really have before. I suppose the best analogy in C#/VB.NET would be the use of a delegate, but in Ruby the syntax is nicer and easier to understand, at least for me.
Here's an example... I've been working on a payment gateway that processes credit card transactions. First I worked on the part that "preauthorizes" the credit card:
class PaymentGateway
def self.preauth!(payment)
begin
if available?
inputs = create_inputs_for_preauth(payment)
result = call_trust_commerce_api(inputs)
else
result = unavailable_result(:preauth)
end
rescue => e
RAILS_DEFAULT_LOGGER.warn "Exception during PaymentGateway.preauth!: #{e.message}"
result = { 'status' => 'error', 'error_type' => e.message }
end
create_authorization_from_result(:preauth, payment, result)
result
end
end
No need to worry about the details here - basically I create the inputs I need to send to our payment processor, call the api with the inputs, and capture the result (the result is a hash); then I create an Authorization row in our database with the results; and finally I return the raw results I got from the payment processor.
Anyway, my tests passed, and I was happy. A few days later I started to work on the part where we "capture" the credit card (our payment processor calls it a "post authorization"):
def self.capture!(payment)
begin
if available?
inputs = create_inputs_for_capture(payment)
result = call_trust_commerce_api(inputs)
else
result = unavailable_result(:postauth)
end
rescue => e
RAILS_DEFAULT_LOGGER.warn "Exception during PaymentGateway.postauth!: #{e.message}"
result = { 'status' => 'error', 'error_type' => e.message }
end
create_authorization_from_result(:postauth, payment, result)
result
end
The alert reader will now be almost asleep, as the capture! code looks almost identical to, and just as boring as, the preauth! method. As good developers, we hate redundancy, right? I wanted to refactor all the common elements of these two methods into a single method that could be called to do the pre- and post-authorization steps, plus any other kind of credit card action I might need later.
As it stands, the methods have only two differences:
- The use of
:preauthor:postauthas a parameter to a couple of functions - The call to create the inputs is either
create_inputs_for_preauthorcreate_inputs_for_capture
The first one was easy - I can just pass that parameter into the new function. It was the second part - creating the input object - that gave me pause. How would the new, genericized method know which method to call? Here's one way:
def self.authorize!(action, payment)
begin
if available?
inputs = action == :preauth ? create_inputs_for_preauth(payment) : create_inputs_for_capture(payment)
result = call_trust_commerce_api(inputs)
else
result = unavailable_result(action)
end
rescue => e
RAILS_DEFAULT_LOGGER.warn "Exception during PaymentGateway.#{action.to_s}!: #{e.message}"
result = { 'status' => 'error', 'error_type' => e.message }
end
create_authorization_from_result(action, payment, result)
result
end
Ugly. What if I add a third action? And I knew I would be adding a third action later on called :credit, which will credit someone's credit card in case they return the product. Should I write a switch statement and update it every time I need to support a new kind of action? No, that didn't sound right. So I decided that the code calling this method would be responsible for creating the input data.
However, I didn't just want to pass the input data as another parameter, because the inputs aren't always needed. I only need the inputs if the payment processing is available at that moment (the available? method controls this behavior, and can be overridden when desired in certain circumstances). So what I needed was a way for the authorize! method to collaborate with the original calling code, and only when needed.
Ruby blocks to the rescue! Now the ternary-operator-turned-ugly-switch-statement code gets replaced with this:
inputs = yield
This means that the authorize! method will call back to the client code at that point. The client code will now responsible for supplying a block of code that can generate the appropriate input data:
self.authorize(:preauth, payment) { create_inputs_for_preauth(payment) }
So now, the final code looks like this:
def self.preauth!(payment)
self.authorize(:preauth, payment) { create_inputs_for_preauth(payment) }
end
def self.postauth!(payment)
self.authorize(:postauth, payment) { create_inputs_for_capture(payment) }
end
private
def self.authorize!(action, payment)
begin
if available?
inputs = yield
result = call_trust_commerce_api(inputs)
else
result = tclink_unavailable_result(action)
end
rescue => e
RAILS_DEFAULT_LOGGER.warn "Exception during PaymentGateway.#{action.to_s}!: #{e.message}"
result = { 'status' => 'error', 'error_type' => e.message }
end
create_authorization_from_result(action, payment, result)
result
end
Now I can easily add more actions without having to change the authorize! method, even though the input data might need to be generated in a different way for each eaction.
Keep in mind, there are many ways I could have refactored this stuff. I chose to use a block to help me come up with a solution this time, but there are certainly other ways you could have removed the redundancies, especially since refactoring techniques is often a matter of taste and style. There's no one right way to do it. But using a block is a technique that those of us new to Ruby might not use too often, so I thought I'd show an example of it here.
And now I get to refactor the authorize! method! :-)




