Rubyize this

It’s not a secret, Ruby syntax offers many possibilities. One thing I enjoy doing once in a while is to take some code I have written a few days before and improve it to make it look more rubyish (read : short, expressive and readable).
I thought it could be fun to make a little game out of it. I’ll put a chunk of code that needs some improvement. Try to analyze and rubyize it.
Be warned though, the code snippet of today is quite stupid. It has been written by Fleebie, the red slime with a trumpet piston shaped mouth.

def manage_ducks(ducks)
  if ducks == nil
    ducks = fetch_some_champions
  else
    unless ducks.won_stanley_cup?
      ducks = fetch_some_champions
    end
  end
  ducks.beat_random_opponent
end

That’s it. How would you rubyize this piece of code?
#UPDATE : It seems that the PRE tag tip I talked about doesn’t work. WordPress strips the pre tags when you are not an administrator. I may have to hack some php files to make it work. Someone knows a wordpress plugin that let the users write nice and indented code snippets?

15 thoughts on “Rubyize this

  1. Here is an alternative to get the idea rolling.

    def manage_ducks(ducks)
      if ducks.nil? || !ducks.won_stanley_cup?
        ducks = fetch_some_champions
      end
      ducks.beat_random_opponent
    end
    
  2. def manage_ducks(ducks)
      ducks = fetch_some_champions if ducks.nil? || !ducks.won_stanley_cup?
      ducks.beat_random_opponent
    end
  3. Nando and Alpha Chen solutions were exactly what I had in mind. IMHO, Nando’s solutions is a bit better, using the “nil?” method, which is easier to understand. Just a minor correction on the logic:

    def manage_ducks(ducks)
      ducks = ducks.fetch_some_champions if ducks.nil? || !ducks.won_stanley_cup?
      ducks.beat_random_opponent
    end
  4. One thing I noticed no one was doing is taking advantage of Ruby returning an object from assignment. The whole ducks.beat_random_opponent thing can do without the ducks.

    # Verbose
    def manage_ducks(ducks)
      unless ducks and ducks.won_stanley_cup?
        fetch_some_champions
      else
        ducks
      end.beat_random_opponent
    end
    # Superterse, if Perl-y
    def manage_ducks(ducks)
      ((ducks && ducks.won_stanley_cup?) ? ducks : fetch_some_champions).beat_random_opponent
    end
    
  5. Thanks everyone for commenting in this first edition of Rubyize this (seeing it was quite popular there will be some more).
    My favorite solution is without a doubt the one by Nando (once you remove the logic mistake like Silvio has pointed out) and Casey. In this situation I prefer the if over unless because it feels more natural. (unless ducks and ducks.won_stanley_cup? can be a bit confusing when you read it).
    I’d also like to talk about RSL suggestions which I find very interesting (the second one is a bit cryptic… but still pretty nice). Although the first solution looks awkward at first, I find it extremely readable and clean. I’ll try to include some of this stuff in my applications in the future.
    RSL, however I don’t understand your last comment. “if ducks.nil?” is definitely not the same as “if ducks”. I guess you wanted to say “unless ducks”.

  6. Woops. You’re right. I did have that backwards. I guess I shouldn’t post comments [especially not ones containing _code_] before I’ve finished my morning coffee.

  7. A little late, but this is an interesting approach:
    def manage_ducks(ducks)
    throw(nil) unless ducks.won_stanley_cup? rescue ducks = fetch_some_champions
    ducks.beat_random_opponent
    end
    A little weird, but it works. If ducks is nil, the unless clause will throw an exception; if
    won_stanley_cup? is false, it throws a nil exception.

Leave a Reply

Your email address will not be published. Required fields are marked *