2

How can this be achieved in Ruby? Can it be done without repeating the variable? Javascript:

b = a || 7 

This assigns a if a is not 0 and 7 otherwise

One specific case is converting date.wday to 7 if it returns 0 (Sunday).

6
  • I'm not sure, but maybe [date.wday, 7].detect { i != 0 } Commented Jun 22, 2016 at 16:37
  • 1
    Given that 0 is not falsey in Ruby it's logically impossible to get what you want. You would have to perform at least one comparison before using the value. Commented Jun 22, 2016 at 16:45
  • 6
    Regarding your original question: just use cwday (instead of wday) – it returns 7 (instead of 0) if the date is a Sunday ;-) Commented Jun 22, 2016 at 16:51
  • wait... Must you use a Date method like wday or not? Commented Jun 22, 2016 at 17:29
  • I had to convert to datetime first, but cwday solved my case. Commented Jun 22, 2016 at 17:34

5 Answers 5

6

Just out of curiosity:

class Object def javascript_or?(other) (is_a?(FalseClass) || nil? || '' == self || 0 == self) ? nil : self end end 

and:

a = b.javascript_or?(7) 
Sign up to request clarification or add additional context in comments.

5 Comments

Readers: mudsie has gone off his medication.
Aye. It’s time to get my pills, thanks @CarySwoveland for the reminder! See ya all tomorrow.
Rubyist will to power
Could also case self which might be faster than this chain of || operators.
@tadman Yeah, I thought about it (though I doubt it could be any faster,) but I on purpose made this answer as cryptic as possible.
6

There are only two falsy values in Ruby: nil and false. So, if you really want this approach

a = b == 0 ? 7 : b 

is a plausible solution, because 0 can't be evaluated as false.

However, a better option for your need is cwday, and not wday. Then you don't need to make this comparison anymore, because it returns 1 for Monday, 2 for Tuesday, and finally 7 for Sunday, as you need.

date = Date.new(2016,19,6) # => Jun 19 2016, Sunday date.cwday # => 7 

3 Comments

@CarySwoveland it's because you already have a 5-digit reputation here, Cary (; I'm just hi-lighting the most important part.
Frankly, I have a 3 digits (and one decimal point, though,) but I don’t need the bold face either.
For the sake of entropy constancy I upvoted it to give 10 rep more :)
3

For the particular case of 0 and 7:

a = (b + 6) % 7 + 1 

:)

1 Comment

:) Nice! Readable as hell!
2

You can use ternary operator:

 date.wday == 0 ? 7 : date.wday 

8 Comments

That I could figure out by myself, any better versions? I edited the question to be just Ruby, not Rails
Ruby does not treat 0 as nil/false. It is one of the things you have to get used to. A better way would be to add your custom method to the Date class. You can find an example here: stackoverflow.com/questions/12343555/…
0 evaluating to true is just part of the language. It's intentional. See, for example: stackoverflow.com/a/10387572/6441528 . If you want an exception, you should do something like build a utility class that provides one. I personally wouldn't override Date, at least not if you're working collaboratively. It'll just confuse anyone who shares your code.
@Aurimas: I don't know if you could figure out about ternary operator by yourself, considering that you could not figure out that 0 in Ruby is not nil/false, which should be the case for operator-|| usage.
While I would use cwday, I think this is a close second. I have no idea why it was downvoted, unless it was by the OP, who found it insulting.
|
1

What you're describing here is less of a logical problem and more of a mapping one:

WEEKDAY_MAP = Hash.new { |h,k| h[k] = k < 7 ? k : nil }.merge(0 => 7) 

This one re-writes 1..6 to be the same, but 0 becomes 7. All other values are nil.

Then you can use this to re-write your day indicies:

b = WEEKDAY_MAP[a] 

If at some point you want to tinker with the logic some more, that's also possible.

4 Comments

Nice, but doesn't it look a bit more complicated than day || 7 ? :D
@Aurimas; That is actually pretty good solution because after initialization (just once), you will not need to use any logical operations to determine your value.
@Aurimas Since Ruby is extremely strict about what's false in a logical sense, || 7 is never going to happen so you may as well abandon that idea: The When in Rome principle applies here. If you're doing a mapping operation, express it as such. In other languages you can take advantage of zero being a false value so the simplest expression of your desire does vary considerably depending on constraints.
In fact, this is the best answer here, hence it narrows down the fact this is a mapping issue.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.