TL;DR: It depends. Are the values meant to be used outside the class? Could they ever become dynamic? Could they change for subclasses?
As @sawa wrote, the downside of the method (written this way) is that a new array and strings are created each time.
A better way to write it would be:
class Example
def self.options
@options ||= ['Yes', 'No', 'Not sure']
end
end
The array is stored in the instance variable @options
, to avoid creating a new array each time.
Written this way, the method is very similar to the constant.
One key difference is if Example
is subclassed, it will be more natural to refine the options
method than the constant OPTIONS
:
class Parent < Example
def self.options
@options ||= [*super, 'Extra']
end
end
To do something similar with constants is difficult. Imagine that your list of options is used in a class method, this would look like:
class Example
OPTIONS = ['Yes', 'No', 'Not sure']
def self.foo(arg)
puts "Available options:",
self::OPTIONS # The self:: is needed here
# ...
end
end
class Parent < Example
OPTIONS = [*superclass::OPTIONS, 'Extra']
end
The tricky thing about constants, is that self::OPTIONS
and OPTIONS
are not the always same, while self.options
and options
are the same. Constants are usually used without specifying the scope (e.g. OPTIONS
instead of self::OPTIONS
) and inheritance will simply not work in that case.
Note that the method gives you the opportunity to make the result dynamic (i.e. return different results depending on other circumstances) without changing the API.
Final note: I'd recommend calling freeze
on your array, to avoid anyone modifying it.