Consider the the following statements:
e #=> NameError: undefined local variable or method `e'...
if false
e = 7
end
e #=> nil
f #=> NameError: undefined local variable or method `f'
f = 7 if false
f #=> nil
As you see, Ruby raises an exception if the value of a local variable (e or f) is sought, but if the variable first appears in a statement, but is not assigned a value, Ruby sets its value to nil. We see that:
a = b unless c.nil?
is the same as:
a = b if c
which is the same as:
a = (c ? b : nil)
which is the same as:
a = c && b
To see why the last expression is equivalent to the preceding two, let's try a couple of examples, both with:
b = 4
c = 2
c && b #=> (2 && 4) => 4
c = nil
c && b #=> (nil && 4) => nil
So I believe you want:
via = reminders_array[i]['value']['via'] &&
reminders_array[i]['value']['bot-input-keyword']
You asked about ||=, which is a form of abbreviated assignment. When Ruby's sees a ||= b she makes the assignment a = b if a is nil or false:
a || a = b
Two more examples, with b still equal to 4:
a = 2
a ||= 4 #=> a || a = 4 => a => 2 || a = 4) => 2
a = nil
a ||= 4 #=> a || a = 4 => a => nil || a = 4 #=> 4
So if a is nil, a remains nil; else a is set to b.
A common use of ||= is:
a = nil
(a ||= []) << 4
#=> [4]
a = [4]
(a ||= []) << 6
#=> [4,6]
In the first instance, a is nil, so a ||= [] converts a to an empty array, to which it appends 4. In the second case, a ([4]) is not nil, so a ||= [] leaves a unchanged ([4]). 6 is then appended to a, making a [4,6].
In addition to ||= there are:
a &&= b #=> a && a = b
a += b #=> a = a + b
a *= b #=> a = a * b
and others (see the doc). A word about a && b. If a is nil, a && b is nil. If a is not nil, a && b is b. Notice that for operators op other than || and &&, a op= b is expanded to a = a op b.