107

Often I need to check if some value is blank and write that "No data present" like that:

@user.address.blank? ? "We don't know user's address" : @user.address

And when we have got about 20-30 fields that we need to process this way it becomes ugly.

What I've made is extended String class with or method

class String
  def or(what)
    self.strip.blank? ? what : self
  end
end

@user.address.or("We don't know user's address")

Now it is looking better. But it is still raw and rough

How it would be better to solve my problem. Maybe it would be better to extend ActiveSupport class or use helper method or mixins or anything else. What ruby idealogy, your experience and best practices can tell to me.

0

7 Answers 7

260

ActiveSupport adds a presence method to all objects that returns its receiver if present? (the opposite of blank?), and nil otherwise.

Example:

host = config[:host].presence || 'localhost'
Sign up to request clarification or add additional context in comments.

2 Comments

this is cool. Default rails posibilities are preffered. Thanx!
Firstly it is preffered because in my solution I should extend String, Fixnum and NilClass at least. And here I can just use clear code without bycles
12

Phrogz sort of gave me the idea in PofMagicfingers comment, but what about overriding | instead?

class String
  def |(what)
    self.strip.blank? ? what : self
  end
end

@user.address | "We don't know user's address"

Comments

2

Since you're doing this in Ruby on Rails, it looks like you're working with a model. If you wanted a reasonable default value everywhere in your app, you could (for example) override the address method for your User model.

I don't know ActiveRecord well enough to provide good code for this; in Sequel it would be something like:

class User < Sequel::Model
  def address        
    if (val=self[:address]).empty?
      "We don't know user's address"
    else
      val
    end
  end
end

...but for the example above this seems like you'd be mixing view logic into your model, which is not a good idea.

1 Comment

Yes, it is bad idea to set defaults in models :) My forms will weep
2

Your or method might have some unwanted side-effects, since the alternative (default) value is always evaluated, even if the string is not empty.

For example

@user.address.or User.make_a_long_and_painful_SQL_query_here

would make extra work even if address is not empty. Maybe you could update that a bit (sorry about confusing one-liner, trying to keep it short):

class String
  def or what = ""
    self.strip.empty? ? block_given? ? yield : what : self
  end
end

@user.address.or "We don't know user's address"
@user.address.or { User.make_a_long_and_painful_SQL_query_here }

2 Comments

good remark. Got it. But why all code will be executed? look: a=2 ; a == 2 ? "ok" : @b = 3 ; @b; #=> nil
It will be executed when making the original call, not with the ternary operator. All the arguments will be evaluated on method call.
1

It is probably better to extend ActiveRecord or individual models instead of String.

In your view, you might prefer a more explicit pattern like

@user.attr_or_default :address, "We don't know the user's address"

1 Comment

Is this part of Active Record? Did not find any references.
0

Ruby:

unless my_str.empty? then my_str else 'default' end

RoR:

unless my_str.blank? then my_str else 'default' end

Comments

0

I recommend to use options.fetch(:myOption, defaultValue) because it works great with boolean flags like the ones mentioned above and therefore seems better to use in general.

Examples

value = {}

puts !!(value.fetch(:condition, true)) # Print true
value = {}
value[:condition] = false

puts !!(value.fetch(:condition, true)) # Print false
value = {}
value[:condition] = true

puts !!(value.fetch(:condition, true)) # Print true
value = {}
value[:condition] = nil

puts !!(value.fetch(:condition, true)) # Print false

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.