Addition of 'or' method to String and NilClass in core_ext

Hey guys,

I find myself doing stuff like this a lot:

self.email.blank? ? self.name : self.email

Anyone feel like adding an ‘or’ method to nil and String (a la blank?) so that this will work:

self.email.or(self.name)

It would be as simple as adding this file to ActiveSupport

activesupport/lib/core_ext/or.rb

class String def or(val) self == “” ? val : self end end

class NilClass def or(val) val end end

I’ll submit a patch of this + tests to LH if people are interested.

Re: [Rails-core] Addition of ‘or’ method to String and NilClass in core_ext Hi,

How about adding some method #foo instead that returns nil if the string is blank and self otherwise, so that you can do:

self.email.foo || self.name

This looks slightly better and more intuitive to me, if we can figure out a descriptive name for the #foo method (I can’t think of any atm, admittedly).

Cheers

Pascal

ifempty?

Pascal Ehlert wrote:

I do it like this:

Long story short:

class Foo   attr_accessor :bar   nillify_blank :bar end f = Foo.new

=> #<Foo:0x4fe8a68>

f.bar = ""

=> ""

f.bar

=> nil

Then you can use the || operator naturally.

Chris

Since ActiveSupport already has #blank?, you can easily give yourself a #nonblank? The symmetry with the Numeric#nonzero? is nice.

-Rob

class String    # Allowing a chain like: string_value.nonblank? || 'default value'    def nonblank?      self unless blank?    end end

class NilClass    # Allowing a chain like: value.nonblank? || 'default value'    def nonblank?      self    end    # so it plays nicely with Numeric#nonzero?    def nonzero?      self    end end

I just found out google groups was bouncing my emails because they were coming from a different address, so to sum them all up in one:

I also realized that I do crap like this a lot too:

self.owner_object_association ? self.owner_object_association : default_thing

Where this would give me:

self.owner_object_association.or_if_blank? default_thing

Maybe just add it to Object?

class Object def or_if_blank?(val) if respond_to? :blank? return self.blank? ? val : self

else
  self

end

end

end

class NilClass def or_if_blank?(val) val end end

That way you get it everywhere blank? is defined (Hash, Array, String, Nil, Numeric)

And the problem with http://gist.github.com/53846 is that I don’t think you can do stuff on regular strings like this:

user_msg = params[:stuff].or_if_blank? ‘didnt type anything’

-Ryan

+1 for or_if_blank?. Some minor suggestions:

1. I think there does not need to be a special implementation for NilClass, since nil.blank? => true.

2. I would consider leaving out the "?" from the method name. ?- methods tend to evaluate to a boolean. This one doesn't.

3. The return can be omitted.

Tim

+1 for the suggestions. I’ll submit a patch to LH later today.

LH ticket created: http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/1815-patch-add-or_if_blank-to-object

I also realized that I do crap like this a lot too:

self.owner_object_association ? self.owner_object_association : default_thing

Where this would give me:

self.owner_object_association.or_if_blank? default_thing

I really don't like "or_if_blank?" It feels like it should live in a gem,

partly because it doesn't seem necessary, and partly because there are too many variants I could see people needing.

  or_if_nil   or_if_blank   or_if_present   or_if_a_plate_of_chips

But saying that,

A clear distinctinction needs to be made between;

  >> a.blank? ? b : a

and

  >> a.or_if_blank?(b)

namely, in the first "b" only gets evaluated ONLY IF "a" is blank in the second, "b" ALWAYS get evaluated.

It's not necessarily a problem. But I worry that we'll see code like;

  >> a.or_if_blank? (call_a_function_that_does_something_bad_but_also_returns_something)

Perhaps a different approach would be something like this

  >> user.bumblebee (:full_name, :email, :something_else, :another_fallback)

which is equivalent to;

  >> if user.full_name.present?   >> return user.full_name   >> elsif user.email.present?   >> return user.email   >> elsif user.something_else.present?   >> return user.something_else   >> elsif user.another_fallback.present?   >> return user.another_fallback   >> end

The bumblebee hovers around the user, looking for a flower with some pollen.

It goes from flower to flower, trying each method in order, and when it finds one that isn't empty, it returns it to the hive.

I cemented the BumbleBee in a gist.

  http://gist.github.com/54501

how do you suggest to make it cater for fallbacks that doesn’t necessarily belong to a method in the object? e.g.:

user.name.blank? ? user.name : “An arbitrary value”

–stephen

how do you suggest to make it cater for fallbacks that doesn't necessarily belong to a method in the object? e.g.:

user.name.blank? ? user.name : "An arbitrary value"

--stephen

BumbleBees are very versatile creatures. And they return a nil if they can't find any flowers.

See the discussion on the ticket for a nice lazy evaluation feature using blocks.

-Tim