Prefer `if object.present?` over `if object`
So you’ve got a controller method
class DressesController < ApplicationController
def show
@dress = Dress.find_by(params.permit(:id))
end
endAnd a view
<div class="<%= dress ? 'dress&.status' : '' %>">Status Indicator</div>Looks good! Works great! Now your app grows, and you have a lot of other views that use the dress. Long after your view has been forgotten, and there’s no clear owner because everyone owns it , but that’s cool because it’s regarded as stable, someone comes along and builds another view
<h1><%= dress.named? ? dress.name.gsub(' ','_').titleize : 'Unnamed' %></h1>Ew gross, so much logic in the view? Gross! Let’s put that logic in a decorator !
class DressDecorator < Draper::Decorator
delegate_all
def title
dress.named? ? dress.name.gsub(' ','_').titleize : 'Unnamed'
end
enddelegate_all will forward all methods it’s sent to whatever it’s decorating.
class DressesController < ApplicationController
def show
@dress = DressDecorator.new(Dress.find_by(params.permit(:id)))
end
endAnd let’s clean up our view.
<h1><%= dress.title %></h1>But now @dress will always be there, even if it decorates nil, so our old code is broken, and will return
NoMethodError (undefined method `status' for #<DressDecorator:0x00007fbc2696d568>)Because of this, it’s always important to code your intention , rather than code to save keystrokes. Use dress.present?, because that’s what you’re checking, even though it’s the same as dress right now.
<div class="<%= dress.present? ? 'dress&.status' : '' %>">Status Indicator</div>In other words, watch out for this…
d = Dress.new(foo: 'bar')
!d.nil?
=> true
d.present?
=> true
d&.foo
=> 'bar'
dd = DressDecorator.new(d)
!dd.nil?
=> true
dd.present?
=> false
dd&.fooTraceback (most recent call last):
NameError (undefined local variable or method `foo' for main:Object)