33

I have a common view that lists two different models. The only difference is that when setting the link_to action, one of the models has a link attribute and the other doesn't. I want to check if the link attribute exists, and if it does, check if it's set. I have the following which works, but I was wondering if there was a better way.

%li
  - if @element.has_attribute?("link") && @element.link
    = link_to @element.title, @element.link
  - else
    = link_to @element.title, @element
sawa
  • 165,429
  • 45
  • 277
  • 381
Eric Norcross
  • 4,177
  • 4
  • 28
  • 53

5 Answers5

38

You could use presence:

= link_to @element.title, (@element.link.presence || @element)

Or, if @element might not have link at all, you could use try:

= link_to @element.title, (@element.try(:link) || @element)
user229044
  • 232,980
  • 40
  • 330
  • 338
ck3g
  • 5,829
  • 3
  • 32
  • 52
13

I believe you can just do @element.attribute? (e.g. @element.link?) (I suppose we could call it "magic attributes".)

This checks for

  • the attribute existing on the model
  • the value not being nil

Exactly what you want.

ahnbizcad
  • 10,491
  • 9
  • 59
  • 85
9

Try using the attributes hash. This hash will return a key => value mapping of all of an activerecord object's attributes.

if @element.attributes['link']
  # Here we are
else
  # default
end
OneChillDude
  • 7,856
  • 10
  • 40
  • 79
0
%li
  = link_to @element.title, @element[:link] || @element
askrynnikov
  • 657
  • 10
  • 15
  • While this code snippet may solve the question, [including an explanation](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) will help people understand the reasons for your code suggestion. – Gerhard Oct 18 '21 at 12:42
  • @Gerhard In my humble opinion, this is the shortest / prettiest version of the code from the question. It does not contain a single extra code symbol. – askrynnikov Oct 18 '21 at 13:17
0

There is also key? which is useful when checking if a property exists on the object, but would otherwise return nil or false.

For example:

a = { b: [] }

a[:b].presence # nil
a.try(:b) # nil
a[:b].present? # false
a.respond_to?(:b) # false

a.key?(:b) # true

So in this case:

%li
  = link_to @element.title, (@element.key?(:link) ? @element.link : @element)
Eric Norcross
  • 4,177
  • 4
  • 28
  • 53