0

I have a written a class:

module SharedConstants
  class Stage
    CONST = {
      created:    0,
      prepared:   1,
      shadowed:   2,
      vmxed:      3,
      sbooted:    4,
      booted:     5,
      saved:      6,
      dontknowen: 7
    }

    def self.method_missing(method_name, *args, &block)
      fail "Constant not defined: #{name}.#{method_name}" if CONST[method_name].nil?
      CONST[method_name]
    end

    def self.respond_to?(method_name, include_private = false)
      CONST[method_name].nil? ? super : true
    end
  end
end

... which works great when we want to access a constant like this:

Stage.created # => 0

Now I want to introduce another set of constants called Foo but I want to dry up the code.

I've tried to move both class methods into the SharedConstant module and 'extend' that module. Tried creating a 'Base' class and deriving from that, but I can get neither approach to work.

Here is my spec example:

require 'rails_helper'

RSpec.describe SharedConstants::Stage, type: :lib do

  [:created, :prepared, :shadowed, :vmxed, :sbooted,
    :booted, :saved, :dontknowen].each do |const|
    it "defines #{const}" do
      expect(described_class.send(const)).to be >= 0
    end

    it "responds to #{const}" do
      expect(described_class.respond_to?(const)).to eq(true)
    end
  end

end

Any ideas are appreciated. Thanks in advance.

Midwire
  • 1,090
  • 8
  • 25
  • Do you mean, `"Constant not defined: CONST[#{method_name}]"`? (I don't know Rails, so I might be missing something.) For arguably better readability, consider `..unless CONST.key?(method_name)` rather than `..if CONST[method_name].nil?`. – Cary Swoveland Oct 10 '14 at 20:59

1 Answers1

0

I would use subclasses and a class method instead of an actual constant.

class ConstantAccessor
  def self.method_missing(method_name, *args, &block)
    super unless const[method_name]
    const[method_name]
  end

  def self.respond_to?(method_name, include_private = false)
    super unless const[method_name]
    true
  end
end

class State < ConstantAccessor
  def self.const
    @const ||= {
      created:    0,
      prepared:   1,
      shadowed:   2,
      vmxed:      3,
      sbooted:    4,
      booted:     5,
      saved:      6,
      dontknowen: 7
    }
  end
end

class AnotherSetOfConstants < ConstantAccessor
  def self.const
    @const ||= {
      something:    0,
      somethingelse:   1,
      another:   2
    }
  end
end
Alex Peachey
  • 4,606
  • 22
  • 18