Ruby Idioms, Part 6

Written on 10:28:00 PM by S. Potter

Tonight I remembered couple more idioms in Ruby and felt compelled to share. In Javafied Ruby code (below) we often see something like the following:

if something
  for role in user.roles
    return true if @@roles.include? role
  end
end
Now when I first started writing Ruby code almost 3 years ago, I thought looping through a collection like above was the nicest way. I quickly found Ruby like the following snippet in code I inherited:
user.roles.each do |role|
  return true if @@roles.include? role
end
At first it took me some time to understand it (remember I was just a poor Java developer with a little Python experience), and I wondered why people would write loops this way. At the time it made no sense. Using this form of looping in Ruby does somewhat violate my "reads more like natural language" coding style preferences, but for some reason this form of looping is now the only one I use in Ruby code. Despite this violation, it feels much more natural. If you are unsure about this yourself, I would encourage you to look into the power of blocks in Ruby. Once you fully appreciate blocks, I think you might be persuaded, (though different opinions make this world more colorful and less bland). The second Ruby idiom is less odd and does enhance code readability more like natural language (again in my opinion):
user.roles.each do |role|
  return true if @@roles.include? role
end if something
Usually when people are having a conversation in English (at least native English speakers), we tend to say things like: We need to verify at least one role the user belongs to is in a pre-defined list of roles if [something]. Non-techies tend to say "if something" at the end of sentences, not at the very beginning (at least this is my experience). So for this reason I think this idiom enhances readability of the code to be more like natural English. For those that start every sentence that contains a conditional with the conditional clause, you have probably been a developer for far too long - go be a beach bum to save yourself before it is too late.

If you enjoyed this post Subscribe to our feed

2 Comments

  1. flip |

    I'm having a lot of fun reading back thru all these idioms, thanks for this.

    Another idiom for this situation:

    return true if (something && user.roles.find{|role| @@roles.include? role})

    or use Set:

    return true if (something && user.roles.to_set.intersection(@@roles).any?)

    Set is in the standard ruby lib and auto-required if you're in Rails, but otherwise you need require 'set'.

    These, of course, are neither better nor worse than your solutions -- it depends whether you want the short-circuiting test of (something) to be more or less prominent.

     
  2. Anonymous |

    Dealing with ruby on the command line a lot I prefer the most concise way:
    something && !(user.roles.find { |role| @@roles.include? role }).nil?

    :)

     

Post a Comment