Reputation: 1990
Is there any way to create aliases across classes? Specifically, from a constant in one class to a class method in another?
Something like
Object.const_set('Foo', proc { Bar.meth })
except having the proc
auto-evaluated at reference-time. (puts Foo
for the above displays the proc #inspect
value; I need to execute Foo.call
to actually invoke bar.meth
-- and that's the extra step I'm trying to finesse around.)
Phrased another way, I would like to alias a constant such that when I say puts Foo
it is exactly equivalent to puts Bar.meth
. If Bar.meth
returns different values at different times, so would Foo
evaluate to the different values accordingly -- because they're the same.
Can this be done?
Thanks!
Upvotes: 2
Views: 2592
Reputation: 8303
This is what you want?
class A
def self.bar
"Test"
end
end
class B
def self.Foo
A.bar
end
def self.const_missing(name)
methods.include?(name.to_s) ? __send__(name) : super
end
end
A.bar
B.Foo
B::Foo
# all returns "Test"
Upvotes: 1
Reputation: 1188
The post above is really great but i was also trying things out in console and got a slightly different solution by not defining a constant in the ruby class "Object".
module Foo
@output = Time.now # You can use 'Bar.meth' just showing the define at reference time
def Foo.to_s
@output
end
end
Output:
$ puts Time.now
# => Tue Feb 22 22:19:23 +0100 2011
$ puts Foo
# => Tue Feb 22 22:19:19 +0100 2011
Upvotes: 0
Reputation: 176412
You can create alias between constants
class Foo
CONST = 3
end
class Bar
CONST = Foo::CONST
end
p Foo::CONST
# => 3
p Bar::CONST
# => 3
You can also reference a method into an other class. But because the value of the constant is elaborated when the assignment is evaluated, you cannot have it changing depending on an other method.
class Foo
def self.const
"value"
end
end
class Bar
CONST = Foo.method(:const)
end
p Foo.const
# => "value"
p Bar::CONST
# => #<Method: Foo.const>
You can try to cheat the interpreter by naming the method like a constant
class Foo
def self.const
"value"
end
end
class Bar
def self.CONST
Foo.const
end
end
p Foo.const
# => "value"
p Bar.CONST
# => "value"
but you will only be able to call Bar.CONST
, not Bar::CONST
.
At this point, I've got a question. Why should you do that? In my opinion, this kind of requirement seems to highlight a design issue.
Upvotes: 1