Alan Coromano
Alan Coromano

Reputation: 26008

defining 2 constants in Ruby

I want to define 2 constants in Ruby such that the second one depends of the first one. Here is what I'm doing:

class MyClass

  MY_CONST = [
    :aaa,
    :bbb,
    :ccc
  ]

  MY_CONST2 = self::MY_CONST << :ddd
end

However, the code below prints the value of the second constant for some reason.

puts MyClass::MY_CONST
puts '------------------'
puts MyClass::MY_CONST2


##################
aaa
bbb
ccc
ddd
------------------
aaa
bbb
ccc
ddd

Why? Is there any way to get rid of it except defining them as def?

def self.my_const
  [:aaa, :bbb, :ccc]
end

def self.my_const2
  self::my_const << :ddd
end

Upvotes: 2

Views: 121

Answers (2)

Michael Geary
Michael Geary

Reputation: 28850

The << operator appends to the array on its left. So when you append :ddd you are appending it to MY_CONST.

One way to avoid this is to use .dup to make a copy of the array before appending:

class MyClass

    MY_CONST = [
        :aaa,
        :bbb,
        :ccc
    ]

    MY_CONST2 = MY_CONST.dup << :ddd
end

(Thanks to @ShawnBalestracci for pointing out the problem with the .clone code I used at first.)

Or use the + operator as @DavidGrayson suggested, which makes a new array instead of modifying the original arrays:

class MyClass

    MY_CONST = [
        :aaa,
        :bbb,
        :ccc
    ]

    MY_CONST2 = MY_CONST + [ :ddd ]
end

Either way prints what you were looking for:

puts MyClass::MY_CONST
puts '------------------'
puts MyClass::MY_CONST2

aaa
bbb
ccc
------------------
aaa
bbb
ccc
ddd

Upvotes: 3

the Tin Man
the Tin Man

Reputation: 160551

You're accessing the constant wrong. It's a class constant, so, while you're defining that class you can reference it locally:

class MyClass

  MY_CONST = [
    :aaa,
    :bbb,
    :ccc
  ]

  MY_CONST2 = MY_CONST + [:ddd]
end

Plus, you're mutating MY_CONST, which isn't what you want to do. << changes the value of MY_CONST then assigns to MY_CONST2 so they're both the same:

MyClass::MY_CONST.object_id
# => 70359163729880
MyClass::MY_CONST2.object_id
# => 70359163729880

After defining MY_CONST2 correctly:

[14] (pry) main: 0> MyClass::MY_CONST
[
    [0] :aaa,
    [1] :bbb,
    [2] :ccc
]
[15] (pry) main: 0> MyClass::MY_CONST2
[
    [0] :aaa,
    [1] :bbb,
    [2] :ccc,
    [3] :ddd
]

Upvotes: 4

Related Questions