开发者

Using constants to create an array without re-specifying the owning class repeatedly

class CAR 
   FORD = 1
   GM = 2
   BMW = 3
end

I want to create an array like:

all_cars = [CAR::FORD, CAR::GM, CAR::BMW]
=>[1, 2, 3]开发者_StackOverflow社区

Is there a way I can initialize this array with typing CAR:: for each element, something like

all_cars = %(FORD GM BMW).map {|ele| "CAR::" + ele}
=>["CAR::FORD", "CAR::GM", "CAR::BMW"]

Not want I wanted


Kind of like Phrogz answer, you could define the constants and initialize the array all at once like this:

class Car
  MAKES = [
    FORD = 1,
    GM = 2,
    BMW = 3
  ].freeze
end

That way, you'd have access to not only individual namespaced constants, but you have an array of them all, as a constant, without the need for repetition:

Car::MAKES # => [1, 2, 3]
Car::FORD  # => 1

Don't forget the freeze or people can mess with your array. You could always dup it if you need to modify it within a particular operation.


  1. Instead of creating an array of constants outside the class, I usually create such collections inside the class itself. In this case, you have no problem:

    class Car
      FORD = 1
      GM   = 2
      BMW  = 3
      MAKES = [ FORD, GM, BMW ]
    end
    
    p Car::MAKES
    #=> [1, 2, 3]
    
  2. But if you are still set on doing what you propose, you want Module#const_get:

    all = %w[ FORD GM BMW ].map{ |k| Car.const_get(k) }
    #=> [1, 2, 3]
    


%w(FORD GM BMW).map{|x| CAR.class_eval(x)} # => [1, 2, 3]

or

%w(FORD GM BMW).map{|x| eval("CAR::#{x}")} # => [1, 2, 3]


This will do it using a module instead of a class:

module CAR 
   FORD = 1
   GM   = 2
   BMW  = 3
end

include CAR

CAR::FORD # => 1
CAR::GM   # => 2
CAR::BMW  # => 3

all_cars = [CAR::FORD, CAR::GM, CAR::BMW]
all_cars # => [1, 2, 3]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜