I often write code to provide a default value upon encountering nil/empty value.
E.g:
category = order.category || "Any"
# OR
category = order.category.empty? ? "Any" 开发者_如何学编程: order.category
I am about to extend the try
method to handle this idiom.
category = order.try(:category, :on_nill => "Any")
# OR
category = order.try(:category, :on_empty=> "Any")
I am wondering if Rails/Ruby has some method to handle this idiom?
Note:
I am trying to eliminate repetition of || / or / ?
operator based idioms.
Essentially I am looking for a equivalent of try
method for handling default substitution scenarios.
Without try
method:
product_id = user.orders.first.product_id unless user.orders.first.nil?
With try
method:
product_id = user.orders.first.try(:product_id)
It is easy to implement a generic approach to handle this idiom, but I want to make sure I do not reinvent the wheel.
See this question. 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'
Perhaps this might serve:
class Object
def subst_if(condition, replacement)
condition = send(condition) if condition.respond_to?(:to_sym)
if condition
replacement
else
self
end
end
end
Used like so:
p ''.subst_if(:empty?, 'empty') # => "empty"
p 'foo'.subst_if(:empty?, 'empty') # => "foo"
It also takes stand-alone conditions, not related to the object:
p 'foo'.subst_if(false, 'bar') # => 'foo'
p 'bar'.subst_if(true, 'bar') # => 'bar'
I'm not crazy about the name subst_if
. I'd borrow whatever name Lisp uses for this function, if I knew it (assuming it exists).
Pretty sure its not baked in. Here is a link to a similar question/answer. It is the approach that I take. Leveraging the ruby: ||=
syntax
An aside: This question also reminds me of the first Railscasts of all time: Caching with instance variables which is a useful screencast if you need to do this kind of operation in a Controller
fetch will work in the case that you are looking for values by index
values of an array or by keys
in a hash ( or ActionController::Parameters
aka params
). Otherwise, you will have to use the ||=
or attempted_value || default_value
as described in the other answers.
The current accepted answer's example is rewritten here:
assuming: config = { my_host_ip: '0.0.0.0' }
config.fetch(:my_host_ip, 'localhost')
# => "0.0.0.0"
config.fetch(:host, 'localhost')
# => "localhost"
a_thru_j = ('a'..'j').to_a
# => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
a_thru_j.fetch(1, 'not here')
# => "b"
a_thru_j.fetch(10, 'not here')
# => "not here"
Note: without the default, you will raise an error when the key
/index
is not present:
config.fetch(:host)
# => KeyError: key not found: :host
params.fetch(:host)
# => ActionController::ParameterMissing: param is missing or the value is empty: host
a_thru_j.fetch(10)
# => index 10 outside of array bounds: -10...10
精彩评论