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 !
hungryblank
October 3, 2007, October 03, 2007 02:50, permalink
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
michiel
October 3, 2007, October 03, 2007 18:52, permalink
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
JohnnyBusca
October 4, 2007, October 04, 2007 06:41, permalink
Thanks very much.. I wanted to get rid of the two yields!
1
puts "#{show_value_or_default(@me, "JohnnyBusca",&:name)} is very happy!"
Matt M.
December 20, 2007, December 20, 2007 15:20, permalink
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
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.