rors.org

Personal website of Dejan Simic, a Ruby On Rails developer working for Less Everything

Self or default if empty, DRY way

I really appreciate following idiom in Ruby:

person.phone || "N/A"

It’s DRY. No need for conditional structures, and repeating person.phone in condition and as return value.

But lets say you don’t control your data source, and there is an empty string instead of nil when data is not available (sounds familiar?). How would you deal with that and keep things simple and DRY?

Well, basicly all you need is a String method that will return nil if string is empty, or self if it’s not empty. String object doesn’t have that kind of method, at least not that specialized. Regexp to rescue. Lets try this:

>> ""[/.+/m]
=> nil

>> “ruby”[/.+/m]
=> “ruby”

Nice. So solution for the problem above is:

person.phone[/.+/m] || "N/A"

Throw andand in game to support both nil and empty value with no cost in complexity:

person.phone.andand[/.+/m] || "N/A"

  • coderrr on 2008-03-23

    w/o need for andand how about:

    s =~ /(.+)/m ? $1 : ‘N/A’

  • coderrr on 2008-03-23

    or better…

    s =~ /.+/m ? $& : ‘N/A’

  • Craig on 2008-03-23

    This seems like “clever” code. Seeing it, I would need to open up IRB to figure out what it does. On the otherhand, person.phone.blank? ? person.phone : “N/A” is obvious. If you’re really obsessed with DRY, create a method default_to for Object so you have person.phone.default_to(“N/A”)

  • Eric Anderson on 2008-03-23

    I agree with Craig 100%. The code it’s obvious and I would much prefer the non-DRY obvious code compared to the mentally complex DRY code. The “default_to” method sounds like a great idea to get the advantages of both (DRY and obvious).

  • Sokolov Yura on 2008-03-24

    I use this:
    somewhere in initialization

    class Object
      def or(v)
        blank? ? v : self
      end
    end
    

    in code

    person.phone.or(“N/A”)
    

  • Greg Weber on 2008-03-24
    gem install methodchain
    require 'rubygems' require 'methodchain' person.phone.and {not empty?} || "N/A"

Any thoughts?



Fork me on GitHub