1

I have this at the beginning of a rails view partial:

<% enabled = true unless defined?(enabled) %>

This is to handle cases when the calling view doesn't pass in the enabled local, by setting a default.

But enabled doesn't get set to true.

I'm aware that of the construct enabled ||= true, but I can't use that here because of the possibility that the passed-in value is false. That would get overwritten with true.

Kelvin
  • 20,119
  • 3
  • 60
  • 68
  • If the passed-in value is `false`, it would NOT get overwritten with `true` in case of `enabled ||= true`. Your answer is good but your logic behind asking this question is questionable at the least :) – ARK Sep 16 '21 at 08:59
  • 1
    @ARK `||=` will overwrite any falsy value. Here's a test that ought to print `[true, false, true]` if overwrite doesn't happen with `false`: `def testme(enabled); enabled ||= true; enabled; end; p [testme(true), testme(false), testme(nil)]`. It prints 3 `true`s. – Kelvin Sep 16 '21 at 21:07
  • Thanks for response. Interesting! I will definitely test this out and research why/how it happens. Interesting. – ARK Sep 20 '21 at 08:19
  • 1
    @ARK If you find this behavior surprising, see [this answer](https://stackoverflow.com/a/1554379) to get a better understanding of `||`. Note that `enabled ||= expression` is equivalent to `enabled = enabled || expression`. – Kelvin Sep 20 '21 at 21:00
  • I tested it in irb and understand what you are implying. Thanks a lot :) – ARK Sep 24 '21 at 11:59

2 Answers2

2

This fixed it:

<%
  unless defined?(enabled)
    enabled = true
  end
%>

It appears this is happening because of how the ruby parser works.

The postfix conditional in the question came after the assignment code, and I think the parser caused the variable to spring into existence with a nil value, making defined? return false.

See this ruby forum post.

Kelvin
  • 20,119
  • 3
  • 60
  • 68
  • @user153138 I didn't necessarily post the question to ask for help. I posted it to help others. I didn't see anything information after Googling that specifically addressed this problem in a succinct way, so I'm hoping others will find it useful. Please comment on the merits of the question and the answer themselves, and not on the time difference. – Kelvin Jun 14 '13 at 20:04
  • @user153138 btw, see [this faq about self-answering](http://stackoverflow.com/help/self-answer) – Kelvin Jun 14 '13 at 20:09
1

You can achieve a similar effect to what you were originally trying to do by combining defined? with the OR operator ||:

defined?(enabled) || enabled = true

Example:

2.4.4 :001 > enabled
NameError: undefined local variable or method `enabled' for main:Object
    from (irb):1
        ...(etc.)
2.4.4 :002 > defined?(enabule) || enabled = true
 => true 
2.4.4 :003 > enabled
 => true 
2.4.4 :004 > enabled = false
 => false 
2.4.4 :005 > defined?(enabule) || enabled = true
 => true 
2.4.4 :006 > enabled
 => true 
David Moles
  • 48,006
  • 27
  • 136
  • 235