user1034127
user1034127

Reputation: 349

ruby, assign the var that is not nill

I have in the html the location variable sometimes is used with a class called "result-hood" sometimes is used with another class called "nearby"

    location = result.search('span.result-hood').text[2..-2]
    location2 = result.search('span.nearby').text[2..-2]

so if one of the above classes is not used the result is nill, my question is how to get always the one that is not nill, I was thinking about the ternary operator "?" , but don't know how to use it. Thanks,

Upvotes: 0

Views: 84

Answers (4)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

CSS supports logical or operations using a comma as the delimiter, so your selector can just be:

location = result.search('span.result-hood,span.nearby').text[2..-2]

XPath also supports logical or operator itself, the equivalent XPath would look like

location = result.search('//span[@class="result-hood"]|//span[@class="nearby"]').text[2..-2]

Upvotes: 3

tadman
tadman

Reputation: 211560

Since you're looking for one or the other you can reduce this code to:

location = result.search('span.result-hood').text[2..-2]
   || result.search('span.nearby').text[2..-2]

Where that search operation could be fairly expensive, so why run it twice when you might need to run it only once. Now that you've minimized it like this you can take it a step further:

location = %w[ span.result-hood span.nearby ].map do |selector|
  result.search(selector).text[2..-2]
end.compact.first

This looks a little complicated but what it does is convert each selector into the text extracted from result.search(...).text[2..-2] and then take the first non-nil value.

That technically computes all possible bits of text before extracting, so you can make it "lazy" and evaluate each one in sequence instead, stopping at the first match:

location = %w[ span.result-hood span.nearby ].lazy.map do |selector|
  result.search(selector).text[2..-2]
end.select(&:itself).first

The nice thing about this approach is you can clean it up a little by declaring a constant in advance:

LOCATIONS = %w[ span.result-hood span.nearby ]

Then later you have more minimal code like this that will automatically accommodate any changes made to that array both in terms of precedence and addition of others:

location = LOCATIONS.lazy.map do |selector|
  result.search(selector).text[2..-2]
end.select(&:itself).first

Upvotes: -1

Arihant
Arihant

Reputation: 745

Ternary operator in ruby:

loc = location.nil? ? location2 : location

Hope this works.

Upvotes: 1

matthewd
matthewd

Reputation: 4420

You want the || ("or") operator:

    location || location2

It returns the left side if that is not nil or false, and otherwise it returns the right side.

Upvotes: 4

Related Questions