In a Rails view, one can use try
to output only if there is a value in the database, e.g
@model.try(:date)
And one can chain trys if, for example, the output is needed as a string
@model.try(:date).try(:to_s)
But what if I need to call a scoped format? I've tried
@model.try(:date).try(:to_s(:long))
@model.try(:date).try(:to_s).try(:long)
What is the correct syntax for this? And what is a good reference for more explanation?
Thanks
From the fine manual:
try(*a, &b)
[...]try
also accepts arguments and/or a block, for the method it is tryingPerson.try(:find, 1)
So I think you want:
@model.try(:date).try(:to_s, :long)
This one won't work:
@model.try(:date).try(:to_s(:long))
because you're trying to access the :to_s
symbol as a method (:to_s(:long)
). This one won't work:
@model.try(:date).try(:to_s).try(:long)
because you're trying to call the long
method on what to_s
returns and you probably don't have a String#long
method defined.
mu is too short's answer shows the correct usage for the try
method with parameters:
@model.try(:date).try(:to_s, :long)
However, if you are using Ruby 2.3 or later, you should stop using try
and give the safe navigation operator a try (no pun intended):
@model&.date&.to_s(:long)
The following answer is here for historical purposes – adding a rescue nil
to the end of statements is considered bad practice, since it suppresses all exceptions:
For long chains that can fail, I'd rather use:
@model.date.to_s(:long) rescue nil
Instead of filling up my view with
try(...)
calls.Also, try to use
I18n.localize
for date formatting, like this:l @model.date, format: :long rescue nil
See: http://rails-bestpractices.com/posts/42-use-i18n-localize-for-date-time-formating
In case you often use try chains without blocks, an option is to extend the Object class:
class Object
def try_chain(*args)
args.inject(self) do |result, method|
result.try(method)
end
end
end
And then simply use @model.try_chain(:date, :to_s)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With