0fe01b8879c35beee8c9b2e9212a5b87

Often in the view you want to display a default value for a field when the object is not existing or the field is blank?

I've created a method in a helper to achieve this, but I think this can be refactored.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# this method returns a default when the object does not exist or the value given in the block does not exist.
#
# Example:
# user = User.find(:first)
# user2 = nil
# 
# show_value_or_default(user)         {|user| user.phone} -> 'phonenumber of user' or '-' of phone is nil or ''.
# show_value_or_default(user2,"leeg") {|user| user.phone} -> 'leeg'
# 
# show_value_or_default(user) {|user| i18n(user.gender)} -> i18n version of the gender. 
# 
def show_value_or_default(object, default = "-")
    (object.nil? or yield(object).blank?) ? default : yield(object)
end

Refactorings

No refactoring yet !

Ada486a7a6724ac155c537674f6942ae

hungryblank

October 3, 2007, October 03, 2007 02:50, permalink

2 ratings. Login to rate!

As a first step you can avoid using the block in the method.
The following doesn't need a block.
Note that in your code if the object is not nil and the method doesn't return blank the method is called twice on the object.

Below there's a code that doesn't use blocks and calls the method only once.

A better solution would be to have your 'object' to return the default value for the method instead of the blank.
Other than that the default values should be constants defined in your classes so they'll be easy to change when needed.

1
2
3
4
5
6
7
8
# samples
# show_value_or_default(user, :phone)
# show_value_or_default(user2, :phone, "leeg")

def show_value_or_default(object, method, default = "-")
  return value if object.respond_to?(method) && !(value = object.send(method)).blank?
  default
end
7c45f63f61e478233f0c2ad3006b178c

michiel

October 3, 2007, October 03, 2007 18:52, permalink

1 rating. Login to rate!

The original solution is fine, except for calling the block twice instead of caching the result. BTW, why test using object.nil? and not just using !object ? Do you really except false values for object?

1
2
3
4
5
6
7
8
def show_value_or_default(object, default = "-")
  return default if object.nil?
  tmp = yield(object)  
  tmp.blank? ? default : tmp 

  # or as a single expression
  # (object.nil? || (tmp = yield(object)).blank?) ? default : tmp
end
0fe01b8879c35beee8c9b2e9212a5b87

JohnnyBusca

October 4, 2007, October 04, 2007 06:41, permalink

No rating. Login to rate!

Thanks very much.. I wanted to get rid of the two yields!

1
puts "#{show_value_or_default(@me, "JohnnyBusca",&:name)} is very happy!"
444c7d8579d3389a76c8497f5cb66c13

Matt M.

December 20, 2007, December 20, 2007 15:20, permalink

No rating. Login to rate!

Here's one that let's you do simple nested calls:

1
2
3
4
5
6
7
8
9
10
11
12
  #
  # def_if_blank(some_obj, :type, :name)
  #
  def def_if_blank(*resource_path)
    default = block_given? ? yield : 'N/A'
    obj = resource_path.shift
    resource_path.each do |method|
      return default if ! obj.respond_to?(method)
      obj = obj.send(method)
    end
    obj
  end

Your refactoring





Format Copy from initial code

or Cancel