11

Starting in Ruby 1.9.3, we can create private constants:

module M
  class C; end
  private_constant :C
end

Is there a good documentation about what this does? Is there a way to get the names of only private constants similar to calling constants

Dave Schweisguth
  • 36,475
  • 10
  • 98
  • 121
sawa
  • 165,429
  • 45
  • 277
  • 381
  • Please explain what use of this you're planning to get. – Ryan Bigg Oct 17 '12 at 22:56
  • Ruby doesn't have private constants. The closest you can get is a class variable, but that isn't terribly private, as it is shared with all subclasses. – Linuxios Oct 17 '12 at 23:04
  • 1
    @RyanBigg I do not have any use for it. I do not understand the relevance of your question to my question. – sawa Oct 17 '12 at 23:35
  • 4
    @sawa Because if you had an actual purpose, and told us, we might have an idea using something Ruby *does* support. Knowing *why* someone wants something is generally valuable, particularly when it's something that doesn't immediately make sense. – Dave Newton Oct 17 '12 at 23:54
  • 1
    @AndrewMarshall Why did you remove the Ruby 1.9.3 tag? This is a feature specific to Ruby 1.9.3. Or did it exist from before that? Please explain. – sawa Oct 18 '12 at 05:38
  • @Linuxios Then, what does `class A; B = 5; private_constant :B; end` mean? – sawa Oct 18 '12 at 05:40
  • 1
    @DaveNewton I am not wanting something. I am just asking how private constants work. I don't understand what you are mentioning by "something that doesn't immediately make sense". – sawa Oct 18 '12 at 05:45
  • @sawa ... You're wanting to know how private constants work. Since there's only barely privacy at all, and private constants were added only recently, most people will try to figure out *why* you want to know so something else can be suggested. I find it difficult to believe this is a difficult concept to understand. And what's the big deal anyway? – Dave Newton Oct 18 '12 at 08:48
  • @DaveNewton How can a method `private_constant` exist without private constant existing? Please explain that in detail. Your comment is totally incomprehensible. – sawa Oct 18 '12 at 08:52
  • Then how did you manage to reply to it at all?! This word, "totally"... or maybe "incomprehensible", may not mean what you think it does. Again: "private" in ruby means almost nothing, it's essentially informational. Carry on. – Dave Newton Oct 18 '12 at 08:57
  • sawa: sorry for the misunderstanding, but this is really just a ruby 1.9.3 feature, and the question should xp.icitly state that. – Linuxios Oct 18 '12 at 13:17
  • 1
    @Linuxios Yes, it is Ruby 1.9.3 specific, and I had that tag. Andrew Marshall somehow removed that tag. I do not understand the reason. – sawa Oct 18 '12 at 17:10

2 Answers2

11

There is no such thing as private constants until Ruby 1.9.3. To get a list of all the constants though, you can simply use constants.

module Mod
  CONST = "value"
end

Mod.constants #=> [:CONST]

From 1.9.3, private_constant was added, but as nothing is really private, you can do...

module Mod
  CONST = "value"
  private_constant :CONST
end

Mod.const_get(:CONST) #=> "value"

I don't think there is a way of getting a list of all the private constants but you can still test the presence of a particular name.

Mod.const_defined?(:CONST) #=> true
tomferon
  • 4,993
  • 1
  • 23
  • 44
4

As of Ruby 2.1, while Module#constants includes only public constants, if you set inherit=false, you will get private constants as well. So if you find a constant in constants(false) but not in constants (and you don't care about inherited constants), that might be a more or less reliable way to tell if it's private.

class Module
  def private_constants
    constants(false) - constants
  end
end

module Foo
  X = 1
  Y = 2
  private_constant :Y
end

puts "Foo.constants = #{Foo.constants}"
puts "Foo.constants(false) = #{Foo.constants(false)}"
puts "Foo.private_constants = #{Foo.private_constants}"

# => Foo.constants = [:X]
# => Foo.constants(false) = [:X, :Y]
# => Foo.private_constants = [:Y]

This is undocumented, and I'm not sure if it's intentional, but empirically it works. I would back it up with unit tests.


Update: It looks like this is a bug in Ruby, and may disappear in a future version.

David Moles
  • 48,006
  • 27
  • 136
  • 235