Dynamically loading and executing within a new module?

Discussion in 'Ruby' started by Lloyd Zusman, Feb 19, 2005.

  1. Lloyd Zusman

    Lloyd Zusman Guest

    I'm not sure what would be the best way to accomplish the following in
    ruby:

    I'm writing a program that periodically looks for files in a certain
    directory. If it finds new ones, I want it to ...

    1. Dynamically create a new module whose name is based somehow upon the
    name of the file.

    2. Do a Kernel#load on the file within this newly created module.

    3. Invoke a method called #init that is defined in this file (assuming
    that this method is actually defined), and do the invocation within
    the context of that newly-created module.

    For example, suppose my directory contains the following files:

    foo.module
    ----------
    def init
    puts "invoking #init within #{self}"
    end

    bar.module
    ----------
    def init
    puts "invoking #init within #{self}"
    end

    When my program encounters the "foo.module" file, I'd like it to do the
    following:

    - create a module called Foo (the name of the file with ".module"
    stripped off and the first letter capitalized) ... or maybe
    SomethingElse::Foo, to avoid collisions with existing packages

    - do a load() of the "foo.module" file within the context of this
    newly created Foo module (or SomethingElse::Foo module)

    - check to see if the #init method is now defined within the
    Foo module; if so, invoke that as a class method within the
    context of that module (i.e., as if it were invoked like
    Foo#init); this should cause the following message to
    print:

    invoking #init within Foo

    What is the recommended way for accomplishing all this within Ruby?

    --
    Lloyd Zusman

    God bless you.
     
    Lloyd Zusman, Feb 19, 2005
    #1
    1. Advertising

  2. Lloyd Zusman

    ES Guest

    On 2/19/2005, "Lloyd Zusman" <> wrote:

    >I'm not sure what would be the best way to accomplish the following in
    >ruby:
    >
    >I'm writing a program that periodically looks for files in a certain
    >directory. If it finds new ones, I want it to ...
    >
    >1. Dynamically create a new module whose name is based somehow upon the
    > name of the file.
    >
    >2. Do a Kernel#load on the file within this newly created module.
    >
    >3. Invoke a method called #init that is defined in this file (assuming
    > that this method is actually defined), and do the invocation within
    > the context of that newly-created module.
    >
    >For example, suppose my directory contains the following files:
    >
    > foo.module
    > ----------
    > def init
    > puts "invoking #init within #{self}"
    > end
    >
    > bar.module
    > ----------
    > def init
    > puts "invoking #init within #{self}"
    > end
    >
    >When my program encounters the "foo.module" file, I'd like it to do the
    >following:
    >
    > - create a module called Foo (the name of the file with ".module"
    > stripped off and the first letter capitalized) ... or maybe
    > SomethingElse::Foo, to avoid collisions with existing packages
    >
    > - do a load() of the "foo.module" file within the context of this
    > newly created Foo module (or SomethingElse::Foo module)
    >
    > - check to see if the #init method is now defined within the
    > Foo module; if so, invoke that as a class method within the
    > context of that module (i.e., as if it were invoked like
    > Foo#init); this should cause the following message to
    > print:
    >
    > invoking #init within Foo
    >
    >What is the recommended way for accomplishing all this within Ruby?


    If you don't just want to write an actual module and then call its #init,
    you could do something like this. Somewhat pseudo:

    Thread.new do
    if fname
    mod = eval fname.capitalize
    data = File.new(fname, 'r') do |f|
    f.read
    end
    mod.module_eval data
    mod.send :init, args
    # ...
    end
    end

    Or sumptin :)

    > Lloyd Zusman


    E
     
    ES, Feb 19, 2005
    #2
    1. Advertising

  3. Lloyd Zusman

    Lloyd Zusman Guest

    ES <> writes:

    > On 2/19/2005, "Lloyd Zusman" <> wrote:
    >
    >> [ ... ]
    >>
    >>When my program encounters the "foo.module" file, I'd like it to do the
    >>following:
    >>
    >> - create a module called Foo (the name of the file with ".module"
    >> stripped off and the first letter capitalized) ... or maybe
    >> SomethingElse::Foo, to avoid collisions with existing packages
    >>
    >> - do a load() of the "foo.module" file within the context of this
    >> newly created Foo module (or SomethingElse::Foo module)
    >>
    >> - check to see if the #init method is now defined within the
    >> Foo module; if so, invoke that as a class method within the
    >> context of that module (i.e., as if it were invoked like
    >> Foo#init); this should cause the following message to
    >> print:
    >>
    >> invoking #init within Foo
    >>
    >>What is the recommended way for accomplishing all this within Ruby?

    >
    > If you don't just want to write an actual module and then call its #init,
    > you could do something like this. Somewhat pseudo:
    >
    > Thread.new do
    > if fname
    > mod = eval fname.capitalize
    > data = File.new(fname, 'r') do |f|
    > f.read
    > end
    > mod.module_eval data
    > mod.send :init, args
    > # ...
    > end
    > end
    >
    > Or sumptin :)


    Thanks. This makes sense.

    However, the "eval fname.capitalize" part doesn't create a new module,
    and that's part of what is confusing me about all this. Given a string
    "Foo", what do I do to it in order to create a module object with that
    name?


    --
    Lloyd Zusman

    God bless you.
     
    Lloyd Zusman, Feb 19, 2005
    #3
  4. Lloyd Zusman

    Lloyd Zusman Guest

    Lloyd Zusman <> writes:

    > ES <> writes:
    >
    >>
    >> [ ... ]
    >>
    >> If you don't just want to write an actual module and then call its #init,
    >> you could do something like this. Somewhat pseudo:
    >>
    >> Thread.new do
    >> if fname
    >> mod = eval fname.capitalize
    >> data = File.new(fname, 'r') do |f|
    >> f.read
    >> end
    >> mod.module_eval data
    >> mod.send :init, args
    >> # ...
    >> end
    >> end
    >>
    >> Or sumptin :)

    >
    > Thanks. This makes sense.
    >
    > However, the "eval fname.capitalize" part doesn't create a new module,
    > and that's part of what is confusing me about all this. Given a string
    > "Foo", what do I do to it in order to create a module object with that
    > name?


    Actually, I now realize that I don't need a bona fide named module, but
    rather, just a way to associate a name with a module. Therefore, I
    think that I can do it more or less like this:

    modhash = Hash.new
    if fname then
    if modhash.has_key?(fname) then
    mod = modhash[fname]
    else
    mod = Module.new
    modhash[fname] = mod
    end
    data = File.new(fname, 'r') do |f|
    f.read
    end
    mod.module_eval data
    mod.send :init, args
    end

    Does this make sense?


    --
    Lloyd Zusman

    God bless you.
     
    Lloyd Zusman, Feb 19, 2005
    #4
  5. Lloyd Zusman

    Christoph Guest

    Lloyd Zusman schrieb:

    >However, the "eval fname.capitalize" part doesn't create a new module,
    >and that's part of what is confusing me about all this. Given a string
    >"Foo", what do I do to it in order to create a module object with that
    >name?
    >
    >

    use Module#new - for example

    ---
    MyNameSpace.const_set fname.capitalize, Module.new
    ---

    You can automate things

    class MyModule < Module
    def initialize(fname)
    ::MyNameSpace.const_set fname.capitalize, self
    # maybe add the the MyModule method
    # using the text file ....
    end
    end

    /Christoph
     
    Christoph, Feb 19, 2005
    #5
  6. Lloyd Zusman

    Christoph Guest

    Lloyd Zusman schrieb:

    >Actually, I now realize that I don't need a bona fide named module, but
    >rather, just a way to associate a name with a module. Therefore, I
    >think that I can do it more or less like this:
    >
    > modhash = Hash.new
    > if fname then
    > if modhash.has_key?(fname) then
    > mod = modhash[fname]
    > else
    > mod = Module.new
    > modhash[fname] = mod
    > end
    > data = File.new(fname, 'r') do |f|
    > f.read
    > end
    > mod.module_eval data
    > mod.send :init, args
    > end
    >
    >Does this make sense?
    >
    >
    >
    >

    You can also use MyNameSpace#const_get
    with a rescue clause

    /Christoph
     
    Christoph, Feb 19, 2005
    #6
  7. Lloyd Zusman

    ES Guest

    On 2/19/2005, "Lloyd Zusman" <> wrote:

    >Lloyd Zusman <> writes:
    >
    >> ES <> writes:
    >>
    >>>
    >>> [ ... ]
    >>>
    >>> If you don't just want to write an actual module and then call its #init,
    >>> you could do something like this. Somewhat pseudo:
    >>>
    >>> Thread.new do
    >>> if fname
    >>> mod = eval fname.capitalize
    >>> data = File.new(fname, 'r') do |f|
    >>> f.read
    >>> end
    >>> mod.module_eval data
    >>> mod.send :init, args
    >>> # ...
    >>> end
    >>> end
    >>>
    >>> Or sumptin :)

    >>
    >> Thanks. This makes sense.
    >>
    >> However, the "eval fname.capitalize" part doesn't create a new module,
    >> and that's part of what is confusing me about all this. Given a string
    >> "Foo", what do I do to it in order to create a module object with that
    >> name?

    >
    >Actually, I now realize that I don't need a bona fide named module, but
    >rather, just a way to associate a name with a module. Therefore, I
    >think that I can do it more or less like this:
    >
    > modhash = Hash.new
    > if fname then
    > if modhash.has_key?(fname) then
    > mod = modhash[fname]
    > else
    > mod = Module.new
    > modhash[fname] = mod
    > end
    > data = File.new(fname, 'r') do |f|
    > f.read
    > end
    > mod.module_eval data
    > mod.send :init, args
    > end
    >
    >Does this make sense?


    Yes, but I'm not sure if I understand why you're doing this in the first
    place. Why don't you just create a named module, store it in a file and
    load
    it when requested instead of just storing the code that'll go in the
    module?

    > Lloyd Zusman


    E
     
    ES, Feb 20, 2005
    #7
  8. Lloyd Zusman

    Lloyd Zusman Guest

    ES <> writes:

    > On 2/19/2005, "Lloyd Zusman" <> wrote:
    >>
    >> [ ... ]
    >>
    >>Actually, I now realize that I don't need a bona fide named module, but
    >>rather, just a way to associate a name with a module. Therefore, I
    >>think that I can do it more or less like this:
    >>
    >> modhash = Hash.new
    >> if fname then
    >> if modhash.has_key?(fname) then
    >> mod = modhash[fname]
    >> else
    >> mod = Module.new
    >> modhash[fname] = mod
    >> end
    >> data = File.new(fname, 'r') do |f|
    >> f.read
    >> end
    >> mod.module_eval data
    >> mod.send :init, args
    >> end
    >>
    >>Does this make sense?

    >
    > Yes, but I'm not sure if I understand why you're doing this in the
    > first place. Why don't you just create a named module, store it in a
    > file and load it when requested instead of just storing the code
    > that'll go in the module?


    Because I want to share code (via symbolic links) and associate it with
    several modules, each module being named differently, based on the file
    in which it resides. Also, I may change the names of these files from
    time to time, and when I do, I don't want to also have to remember to
    also change the module names contained in these files.

    By dynamically naming the modules in the ways we have been discussing,
    this allows me to have a unique namespace for each file-based module
    that I create, even if several files share the same contents via
    symbolic links. And this is ensured no matter how many renames
    or symbolic link changes I make.

    --
    Lloyd Zusman

    God bless you.
     
    Lloyd Zusman, Feb 20, 2005
    #8
  9. Lloyd Zusman

    Lloyd Zusman Guest

    Christoph <> writes:

    > Lloyd Zusman schrieb:
    >
    >>Actually, I now realize that I don't need a bona fide named module, but
    >>rather, just a way to associate a name with a module. Therefore, I
    >>think that I can do it more or less like this:
    >>
    >> modhash = Hash.new
    >> if fname then
    >> if modhash.has_key?(fname) then
    >> mod = modhash[fname]
    >> else
    >> mod = Module.new
    >> modhash[fname] = mod
    >> end
    >> data = File.new(fname, 'r') do |f|
    >> f.read
    >> end
    >> mod.module_eval data
    >> mod.send :init, args
    >> end
    >>
    >>Does this make sense?
    >>
    >>
    >>
    >>

    > You can also use MyNameSpace#const_get
    > with a rescue clause


    Yes ... makes sense. Thanks.

    --
    Lloyd Zusman

    God bless you.
     
    Lloyd Zusman, Feb 20, 2005
    #9
  10. Lloyd Zusman

    Lloyd Zusman Guest

    Christoph <> writes:

    > Lloyd Zusman schrieb:
    >
    >>However, the "eval fname.capitalize" part doesn't create a new module,
    >>and that's part of what is confusing me about all this. Given a string
    >>"Foo", what do I do to it in order to create a module object with that
    >>name?
    >>
    >>

    > use Module#new - for example
    >
    > ---
    > MyNameSpace.const_set fname.capitalize, Module.new
    > ---
    >
    > You can automate things
    >
    > class MyModule < Module
    > def initialize(fname)
    > ::MyNameSpace.const_set fname.capitalize, self
    > # maybe add the the MyModule method
    > # using the text file ....
    > end
    > end
    > /Christoph


    Aha! ... that's a great idea. I love how ruby (like Smalltalk) makes
    classes, objects, etc. into first-class objects.

    --
    Lloyd Zusman

    God bless you.
     
    Lloyd Zusman, Feb 20, 2005
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. TheDustbustr
    Replies:
    2
    Views:
    371
    Christian Tismer
    Aug 17, 2003
  2. hg
    Replies:
    7
    Views:
    297
    laurent rahuel
    Jan 5, 2007
  3. Peter Otten
    Replies:
    3
    Views:
    737
    Nobody
    Feb 15, 2010
  4. Alex Maghen
    Replies:
    3
    Views:
    618
    Jerry Weng
    Aug 12, 2010
  5. Travis Whitton

    Problem Dynamically Loading a Module

    Travis Whitton, Sep 15, 2003, in forum: Ruby
    Replies:
    2
    Views:
    171
    Travis Whitton
    Sep 15, 2003
Loading...

Share This Page