philihpAboutPGPLightning

Prefer `if object.present?` over `if object`

Philihp Busby,2 min read

So you’ve got a controller method

class DressesController < ApplicationController def show @dress = Dress.find_by(params.permit(:id)) end end

And 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 end

delegate_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 end

And 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&.foo
Traceback (most recent call last): NameError (undefined local variable or method `foo' for main:Object)

GitHub · Bluesky · LinkedIn · Instagram · KeybaseRSS

Built from 8f0906ac CC BY 4.0 — with love from San Francisco.