Rails Object#presence vs Object#try
- Categories:
- rails
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 || "-"
Sponsored Links
- Register to Digital Ocean cloud with this link and get $200 credit
- Looking for cheap CDN? Bunny is the answer
- Alternative Cloud besides AWS and Digital Ocean