0

I write 2 method, one with ternary operator and one with if..else..end.

def test_a()
  return (a.blank? or a.body.blank?) ? {} : a.body
end

def test_b()
  if a.blank? or a.body.blank?
    return {}
  else
    return a.body
  end
end

I think both of them seem to be the same.

But in RubyMine it show warning at a.body of ternary :

Nil dereference may occur ruby in ternary operator

enter image description here

Am I using the wrong syntax?

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
quangkid
  • 1,287
  • 1
  • 12
  • 31
  • 2
    First of all, `||` is preferred over `or` due to precedence concerns. But other than that, your code looks fine. – Marek Lipka Jun 07 '19 at 06:44
  • There is no method `blank?` in Ruby in the first place. – Aleksei Matiushkin Jun 07 '19 at 06:59
  • Also, in both methods the local variable `a` is not ever defined. – Aleksei Matiushkin Jun 07 '19 at 07:01
  • "Am I using the wrong syntax?" – No. If you were using wrong syntax, you would get a `SyntaxError`. A `nil` dereference clearly is not a syntactic issue, it is a semantic one. Plus, this is not an error, just a warning. – Jörg W Mittag Jun 07 '19 at 07:03
  • 1
    RubyMine cannot parse your condition and concludes that `a` might be `nil` in either case, hence the warning. Using `||` instead of `or` and removing the parentheses should fix it. – Stefan Jun 07 '19 at 07:05
  • My *guess* without knowing the internals of RubyMine would be that the static analyzer gets confused in one snippet but not in the other. Ruby is notoriously hard to analyze statically, so oddities, false positives, and false negatives, are to be expected. – Jörg W Mittag Jun 07 '19 at 07:06
  • @AlekseiMatiushkin Sorry, my bad. It's Ruby on Rails. – quangkid Jun 07 '19 at 07:15

3 Answers3

1

not sure about rubymine itself, but the

nil dereference may occur

notification happens since you access a.body.blank? before you check whether body is nil or not. some avoid this by using a.body && a.body.blank?. in ruby 2.3 there is a short syntax for this a.body&.blank?

Mr.
  • 9,429
  • 13
  • 58
  • 82
1

As @Stefan's answer : Using || instead of or and ...

...removing the parentheses should fix it

def test_a
  a.blank? || a.body.blank? ? {} : a.body
end

I think this is quick right answer in my case. Tested in RubyMine.

quangkid
  • 1,287
  • 1
  • 12
  • 31
1

You should be able to write that expression as follows:

a&.body.presence || {}
  • If a is nil it will return {}.
  • If a.body is nil it will also return {}
  • If a.body is blank it will also return {}
  • If a.body is present, it will return a.body
fphilipe
  • 9,739
  • 1
  • 40
  • 52