In the Rails world, there are many ways to show attribute from object with nil checker. Here are my favorite syntax

seller = Seller.first
# => #<Seller id: 1, name: "Rails Seller", phone: "">

# without try / presence method
seller && seller.name
# => "Rails Seller"
seller && seller.phone
# => ""

# with try method
seller.try(:name)
# => "Rails Seller"
seller.try(:phone)
# => ""

# with presence emthod
seller.name.presence
# => "Rails Seller"
seller.phone.presence
# => nil

Object#try and Object#presence are methods from Object class from ActiveSupport. Because I am curious about the performance, I run the benchmark with these Ruby and Rails specifications:

  • Ruby version: 2.5.0
  • Rails version: 5.1.4

Condition 1: name attribute has a string value

seller.name
 => "Rails Seller"

Benchmark script, run via Rails console:

Benchmark.bmbm(7) do |x|
  x.report("seller && seller.name")   { seller && seller.name }
  x.report("seller.try(:name)") { seller.try(:name) }
  x.report("seller.name.presence")  { seller.name.presence }
end

Benchmark result:

# First test
Rehearsal ---------------------------------------------------------
seller && seller.name   0.000000   0.000000   0.000000 (  0.000016)
seller.try(:name)       0.000000   0.000000   0.000000 (  0.000025)
seller.name.presence    0.000000   0.000000   0.000000 (  0.000012)
------------------------------------------------ total: 0.000000sec

                            user     system      total        real
seller && seller.name   0.000000   0.000000   0.000000 (  0.000019)
seller.try(:name)       0.000000   0.000000   0.000000 (  0.000044)
seller.name.presence    0.000000   0.000000   0.000000 (  0.000033)

# Second test
Rehearsal ---------------------------------------------------------
seller && seller.name   0.000000   0.000000   0.000000 (  0.000022)
seller.try(:name)       0.000000   0.000000   0.000000 (  0.000046)
seller.name.presence    0.000000   0.000000   0.000000 (  0.000020)
------------------------------------------------ total: 0.000000sec

                            user     system      total        real
seller && seller.name   0.000000   0.000000   0.000000 (  0.000012)
seller.try(:name)       0.000000   0.000000   0.000000 (  0.000146)
seller.name.presence    0.000000   0.000000   0.000000 (  0.000017)

Condition 2: attribute has a blank string value

seller.phone
 => ""

Benchmark script, run via Rails console:

Benchmark.bmbm(7) do |x|
  x.report("seller && seller.phone")   { seller && seller.phone }
  x.report("seller.try(:phone)") { seller.try(:phone) }
  x.report("seller.phone.presence")  { seller.phone.presence }
end

Benchmark result:

# First test
Rehearsal ----------------------------------------------------------
seller && seller.phone   0.000000   0.000000   0.000000 (  0.000016)
seller.try(:phone)       0.000000   0.000000   0.000000 (  0.000068)
seller.phone.presence    0.000000   0.000000   0.000000 (  0.000010)
------------------------------------------------- total: 0.000000sec

                             user     system      total        real
seller && seller.phone   0.000000   0.000000   0.000000 (  0.000021)
seller.try(:phone)       0.000000   0.000000   0.000000 (  0.000035)
seller.phone.presence    0.000000   0.000000   0.000000 (  0.000019)

# Second test
Rehearsal ----------------------------------------------------------
seller && seller.phone   0.000000   0.000000   0.000000 (  0.000019)
seller.try(:phone)       0.000000   0.000000   0.000000 (  0.000066)
seller.phone.presence    0.000000   0.000000   0.000000 (  0.000012)
------------------------------------------------- total: 0.000000sec

                             user     system      total        real
seller && seller.phone   0.000000   0.000000   0.000000 (  0.000017)
seller.try(:phone)       0.000000   0.000000   0.000000 (  0.000111)
seller.phone.presence    0.000000   0.000000   0.000000 (  0.000015)

Conclusion

Based on this benchmark, try method has the worst performance. But in real world use case I think you can ignore these benchmarks result because the number are too small. I personally prefer to use presence method to get value of an attribute.

Another reason why I prefer presence because it returns nil, so I can use this syntax:

seller.name.presence || "-"