that static method util_name is needed to prevent nil when I need an empty string if it's nil.
def self.util_name(value)
return '' if value.nil?
value.name
end
Okay, given that bit of context you can remove the Budget::util_name
method entirely because it isn't doing anything useful. There are two ways of conditionally calling a method on an object that might be nil
, one provided by the framework and one by the language.
If you are using Ruby 2.2 or earlier, use the try method.
value.try(:name)
if you are using Ruby 2.3 or above, you can use the safe navigation operator
value&.name
In either case, you don't need to specifically test for nil
because it will be automatically coerced into an empty string when interpolated.
"#{envelope_quantity&.name} - envelope #{envelope_size&.name} #{envelope_paper&.name} #{envelope_color&.name} #{envelope_grammage&.name} #{envelope_model&.name} #{envelope_print&.name}"
That's much more reasonable, still probably a bit too long. You could use string templates:
"%{quantity} - envelope %{size} %{paper} %{color} %{grammage} %{model} %{print}" % {
quantity: envelope_quantity&.name,
size: envelope_size&.name,
paper: envelope_paper&.name,
color: envelope_color&.name,
grammage: envelope_grammage&.name,
model: envelope_model&.name,
print: envelope_print&.name
}
But I want to focus on something I noticed about this code sample. Every single method begins with envelope
which probably means that these methods are telling you they should be a separate object. If you extract this data into a value object, then the natural location for this helper method becomes obvious...
class Envelope < Struct.new(:quantity, :size, :paper, :color, :grammage, :model, :print)
def to_s
"#{quantity&.name} - envelope #{size&.name} #{paper&.name} #{color&.name} #{grammage&.name} #{model&.name} #{print&.name}"
end
end
Undoubtedly the real code would be more complicated than that, just food for thought.