I have a two part question
Best-Practice
module Writer
class << self
def output(s)
puts upcase(s)
end
private
def upcase(s)
s.upcase
end
end
end
Writer.output "Hello World"
# -> HELLO WORLD
Writer.upcase "Hello World"
# -> so.rb:16:in `<main>': private method `upcase' called for Writer:Module (NoMethodError)
What's about storing methods as lambdas within class variables/constants?
module MyModule
@@my_secret_method = lambda {
# ...
}
# ...
end
For test:
UPD: huge update of this code after 6 years shows cleaner way to declare private method d
module A
@@L = lambda{ "@@L" }
def self.a ; @@L[] ; end
def self.b ; a ; end
class << self
def c ; @@L[] ; end
private
def d ; @@L[] ; end
end
def self.e ; c ; end
def self.f ; self.c ; end
def self.g ; d ; end
def self.h ; self.d ; end
private
def self.i ; @@L[] ; end
class << self
def j ; @@L[] ; end
end
public
def self.k ; i ; end
def self.l ; self.i ; end
def self.m ; j ; end
def self.n ; self.j ; end
end
for expr in %w{ A.a A.b A.c A.d A.e A.f A.g A.h A.i A.j A.k A.l A.m A.n }
puts "#{expr} => #{begin ; eval expr ; rescue => e ; e ; end}"
end
Here we see that:
A.a => @@L
A.b => @@L
A.c => @@L
A.d => private method `d' called for A:Module
A.e => @@L
A.f => @@L
A.g => @@L
A.h => private method `d' called for A:Module
A.i => @@L
A.j => @@L
A.k => @@L
A.l => @@L
A.m => @@L
A.n => @@L
1) @@L
can not be accesses from outside but is accessible from almost everywhere
2) class << self ; private ; def
successfully makes the method d
inaccessible from outside and from inside with self.
but not without it -- this is weird
3) private ; self.
and private ; class << self
do not make methods private -- they are accessible both with and without self.
I think the best way (and mostly how existing libs are written) to do this is by creating a class within the module that deals with all the logic, and the module just provides a convenient method, e.g.
module GTranslate
class Translator
def perform( text ); translate( text ); end
private
def translate( text )
# do some private stuff here
end
end
def self.translate( text )
t = Translator.new
t.perform( text )
end
end