In my project Bar
, I have this class Foo
, whose instances represent unique, named real-world objects. References to these instances are scattered under good care around the data structures in my project, but also, I have decided to make them accessible by their names. For this purpose, class Foo itself traces its instances, like
module Bar
class Foo
attr_reader :name
def initialize( name )
@name = name
end
def self.new *args, &block
new_instance = super
n_i_name = new_instance.name
( @instances ||= {} ).merge! new_instance => n_i_name
return new_instance
end
def inspect; "Foo instance #{name}" end
end
end
Now this is a common pattern. Typically, to access the instances, one can establish a public class method in Foo
:
class << Bar::Foo
def instance( i )
case i
when self then i
else @instances.rassoc( i ).first end
end
end
i = Bar::Foo.new "John Smith"
#=> Foo instance John Smith
i.object_id
#=> 68997470
Bar::Foo.instance( "John Smith" ).object_id
#=> 68997470
But the problem is, that there are analogical classes with named instances under Bar
module, such as Bar::Baz
, Bar::Quux
and so on, which need to access Foo
instances and each other by name. So I figured that keeping order in the way these various classes access each others instances by name is the responsibility of Bar
module itself, and I created public module methods in it:
module Bar
# Foo method blah blah blah...
def self.Foo( i ); Foo.instance i end
# Baz method blah blah blah...
def self.Baz( i ); Baz.instance i end
# Quux method blah blah blah...
def self.Quux( i ); Quux.instance i end
end
Whenever classes Foo
, Baz
, Quux
refer to each other, they use Bar.Foo( "John Smith" )
style calls, which makes possible referring to these instances also by their unique names. Now my problem is, that this still doesn't seem 100% kosher to me. When I run rdoc
to create documentation for Bar
module, public class methods #Foo
, #Baz
, #Quux
make it to the documentation. But these are not really intended to be a part of the user interface. So I have the following options, each of which has a problem:
Include
#Foo
,#Baz
,#Quux
in the user interface. Problem: The user does not really need them that badly; it was not my design intention to have them in UI.Add
# :nodoc:
directive to them to preventrdoc
from documenting them. Problem: It does not feel right. It is not likeBar.Foo
and friends were excluded from the user interface. It feels more like they are still part of the UI, but undocumented, secret. I don't want that.Declare them private using
#private_class_method
. But then, even if the instances#Foo
,#Baz
,#Quux
access each other by name during normal operation, they, too, have to useBar.send :Foo, "John Smith"
style.
The question: The option 3. seems least harmful. But still, it is not perfect. Ideally, I would like to have methods Bar.Foo
, Bar.Baz
, Bar.Quux
protected in such way, that these guys can call each other by names by simply calling Bar.Foo "John Smith"
, while the user has to use Bar.send :Foo, "John Smith"
, and these module methods are not documented for the user. What other options, if any, do I have to achieve this state of affairs? Is there a way to selectively allow some classes to use somebody else's private methods at will? Also, I have no experience with protected class methods, could that be a solution? Thanks for your time spent reading this.