Sam J
Sam J

Reputation: 75

Ruby protected constants, or similar implementation

I would like to implement the following:

module A
  class B
  end
  # can call A:B within module
end

# cannot call A:B outside of module (like private constant)

I basically want private constants but I would like to be able to call them with namespacing within the module.

It seems to me I need some sort of protected behaviour on the B constant within A, but as far as I am aware, Ruby does not have protected constants.

I am keen to hear ideas on how this can be implemented.

Upvotes: 0

Views: 389

Answers (1)

Cary Swoveland
Cary Swoveland

Reputation: 110755

That can be done but I have no idea why you'd want to do it.

module A
  class B
    def greeting
      puts "hi within #{self}"
    end
  end
  puts "constants within A = #{constants}"
  B.new.greeting
  # <more code>
  # lastly...
  const_set(:B, nil)
end

displays:

constants within A = [:B]
hi within #<A::B:0x00005b2a18ffc538>
warning: already initialized constant A::B
warning: previous definition of B was here

Then,

A::B.new.greeting
  NoMethodError (undefined method `new' for nil:NilClass)

If desired, you can add '-W' or -W0 to the command line to suppress the warning messages.

I understand ActiveSupport has a method Object::remove_constant allowing one to replace const_set(:B, nil) (or const_set("B", nil)) with:

Object.public_send(:remove_const, :B)

which may be preferable.

Upvotes: 1

Related Questions