3

I just tried to run some code that looked like this

def get_proj4(srid, type=nil)
  type.downcase! if type
  case type
  when nil || "epsg"
   open("http://spatialreference.org/ref/epsg/#{srid}/proj4/").read
  when "esri"
   open("http://spatialreference.org/ref/esri/#{srid}/proj4/").read
  end
end

and it didn't run properly, returning nil every time. wrapping the nil || "epsg" in parentheses didn't work either

It turns out ruby wouldn't allow me to use the || operator in this

Now I assume ruby takes the case/when method and ultimately breaks it down into a group of conditionals looking something like

x = type
  if x == (nil || "epsg")
    y = ...runs code...
  elsif x == "esri"
    y = ...
  end
x = nil
y

but obviously it does not. What's going on here?

Thanks

boulder_ruby
  • 38,457
  • 9
  • 79
  • 100

1 Answers1

2

The expression is evaluated first so when nil || "espg" is equivalent to when "espg"1 - it will never match nil.

To match either-or, separate the options with a comma:

case type
when nil, "espg" ..
when "esri" ..

Or, alternatively, perhaps normalize the value:

case (type || "espg")
when "espg" ..
when "esri" ..

Or use the other form that resembles an if-else:

case
when type.nil? || type == "espg" ..
when type == "esri" ..

Or some combination of everything :)


1 This is also the same reason why the example if is suspect. It should probably be written like:

if type.nil? || type == "espg"
user2246674
  • 7,621
  • 25
  • 28
  • ahh `x == nil || "epsg"` **does** match nil **but**, as it the line continues to evaluate, it has to move on from that match because of the nature of the || operator i.e. `(nil || false) => next`. gotcha, and then it doesn't match "epsg", and its on to the next one...(?) that kind of makes sense – boulder_ruby Sep 24 '13 at 00:38
  • @boulder_ruby If it written like that, then yes - but it will always be a truthy expression (as `anything || "espg"` is truthy) so it should never match any alternative branch. – user2246674 Sep 24 '13 at 00:39
  • nil isn't `anything`. what's anything? ruby doesn't have an object for that!!! except for `Object`, of course...erm..... – boulder_ruby Sep 24 '13 at 00:41
  • But don't try to match nil, got it. That's what false is for (?) – boulder_ruby Sep 24 '13 at 00:43
  • @boulder_ruby I meant `anything` to mean it doesn't matter what the `x == nil` expression evaluates to - if it evaluates to a truthy value that will be the reuslt, but if it evaluates to a falsey value (namely, false) then "espg" (a truthy value) will result. `a || b` is short-circuiting, and will always evaluate to a truthy-value if either expression a *or* b evaluates truthy; otherwise it will result in false. – user2246674 Sep 24 '13 at 00:45