Search code examples
rubylogicoperators

Using operators, how to set a variable equal to one of two other variables depending on which one has a value, in Ruby?


When there are only two states for instance variable "a", either it has a value or not, and there is only one possible state for instance variable "b", it has a value. I can set "a" equal to "b" if "a" does not have a value via:

@a = nil
@b = "world"

def set_a
    @a ||= @b
end

set_a

p @a
 => "world"
@a = "hello"
@b = "world"

def set_a
    @a ||= @b
end

set_a

p @a
 => "hello"

But, what if there is more than one option for "a" to be set to? For example, I want to set instance variable "a" to either "b" or "c" depending on which has a value. In the program, only either "b" or "c" will have a value, always one but never both. Is there a way, using operators to write something like the following:

if @a == nil
   if @b == nil
      @a = @c
   else
      @a = @b
   end
end

I was trying to write something that looks like this:

def set_a
    @a ||= (@b || @c)
end

But, if @a had a value it would remain. Which is what I want. However, if @a was nil, then it would not take on the value of either @b or @c, it would remain nil.

Thank you for you time.


Solution

  • You can write

    Module.const_defined?(:A) ? A : (B == true ? B : C)
    

    to obtain the value of A.

    A not defined
    B = true
    Module.const_defined?(:A) ? A : (B == true ? B : C)
      #=> true
    
    A not defined
    B = false
    Module.const_defined?(:A) ? A : (B == true ? B : C)
      #=> 42
    
    A = "cat"
    B = false
    C = 42
    Module.const_defined?(:A) ? A : (B == true ? B : C)
      #=> "cat"
    

    See Module#const_defined?.