[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Access module's anonymous parent

Xavier Shay

10/27/2008 8:15:00 AM

I want the following eval to output "Foo called", without having a named
constant, since in leaks in to the calling scope:

m = Module.new
m.instance_eval do
def foo
puts "Foo called"
end
ParentSelf = self
class self::A
ParentSelf.foo # How do I do this without a constant?
end
end
a = m.const_get('A').new
puts ParentSelf # This should raise - constant should not exist


I have found given self and a global function, I can use the string
representation of the anon module to find it in ObjectSpace. Clearly
this is dodgy though:

def depend(instance, file)
q = self.to_s.split('::').first.to_s
found = nil
ObjectSpace.each_object(Module) do |m|
found = m if q == m.to_s
end
found.depend(file)
end

m = Module.new
m.instance_eval do
def depend(file)
puts "Depend called with file: #{file}"
end

class self::A
depend(self, 'afile.rb')
end
end
--
Posted via http://www.ruby-....

4 Answers

Brian Candler

10/27/2008 8:41:00 AM

0

Is this what you're looking for?

m = Module.new
m.instance_eval do
def foo
puts "Foo called"
end
parent = self
child = class self::A; self; end
child.class_eval { parent.foo }
end
a = m.const_get('A').new
puts ParentSelf # This should raise - constant should not exist

(you can also use 'm.foo' instead of 'parent.foo', which means you can
remove the assignment 'parent = self')
--
Posted via http://www.ruby-....

Xavier Shay

10/27/2008 9:54:00 PM

0

Brian Candler wrote:
> Is this what you're looking for?
>
> m = Module.new
> m.instance_eval do
> def foo
> puts "Foo called"
> end
> parent = self
> child = class self::A; self; end
> child.class_eval { parent.foo }
> end
> a = m.const_get('A').new
> puts ParentSelf # This should raise - constant should not exist
>
> (you can also use 'm.foo' instead of 'parent.foo', which means you can
> remove the assignment 'parent = self')

I would have liked to keep the more familiar class syntax without
resorting to class_eval

> parent = self
> child = class self::A; self; end
> child.class_eval { parent.foo }

I'm autoloading a file, it contains this part, so it's basically the
public interface.

> class self::A
> parent.foo

And for that reason this is a much nicer, I think. But if it can't be
done like this, it can't be done...
--
Posted via http://www.ruby-....

Pit Capitain

10/28/2008 7:05:00 AM

0

2008/10/27 Xavier Shay <contact@rhnh.net>:
> I'm autoloading a file, it contains this part, so it's basically the
> public interface.
>
>> class self::A
>> parent.foo
>
> And for that reason this is a much nicer, I think. But if it can't be
> done like this, it can't be done...

Xavier, I don't know why you want to have an anonymous module with a
local constant, but if you really need this and are willing to change
the public interface a little bit you could do

m = Module.new
m.module_eval do
# methods for dependent classes
def depend(file)
puts "#{self} depends on #{file}"
end
# methods to define a dependent class
def self.const_missing(name)
const_set(name, Class.new)
end
def self.dependent_class(cls, &blk)
parent_module = self
cls.class_eval do extend(parent_module) end
cls.class_eval(&blk)
end
# public interface for dependent classes
dependent_class self::A do
depend("afile.rb")
end
end

Regards,
Pit

Xavier Shay

10/28/2008 7:43:00 AM

0

Pit Capitain wrote:
> 2008/10/27 Xavier Shay <contact@rhnh.net>:
>> I'm autoloading a file, it contains this part, so it's basically the
>> public interface.
>>
>>> class self::A
>>> parent.foo
>>
>> And for that reason this is a much nicer, I think. But if it can't be
>> done like this, it can't be done...
>
> Xavier, I don't know why you want to have an anonymous module with a
> local constant
Hot loading of code. I'm being a bit anal about it, also I'm just
curious :)
Would be nice to not need the dependent_class bit, but it's not so bad.

I had to hack your code a bit to get what I want, which is this:

m = Module.new
m.instance_eval do
self::Depend = []

def self.const_missing(name)
const_set(name, Class.new)
end

def self.dependent_class(cls, &blk)
parent_module = self
(class << cls; self; end).send(:define_method, :depend) do |file|
parent_module::Depend << file
end
cls.class_eval(&blk)
end

dependent_class self::A do
depend("afile.rb")

def foo
"foo"
end
end
end

a = m.const_get('A').new
puts a.foo # => foo
puts m::Depend.inspect # => ["afile.rb"]

Thanks!
Xavier
--
Posted via http://www.ruby-....