Loading a file without cluttering the global namespace

Discussion in 'Ruby' started by Benjamin Hepp, Jul 2, 2005.

  1. Hello,

    I'm trying to build a module-mechanism in ruby so that I am able to load a
    ruby-file without cluttering up the global namespace of the program.

    For example I want to be able to load a ruby-file, search for methods in
    it, possibly execute one of them and then "unload" the file. When I call
    Kernel#load with wrap = true, everything of the new file is put into an
    anonymous Module, but every other file loaded in the new file itself is
    put into the global namespace again.

    My questions:

    Is it at all possible to prevent this? If so, how to do it?
    Can I access the anonymous Module in an easy manner?
    How to delete/undefine a class or a method?

    Thanks in advance
    Benjamin Hepp
     
    Benjamin Hepp, Jul 2, 2005
    #1
    1. Advertising

  2. On 7/2/05, Benjamin Hepp <> wrote:
    > Is it at all possible to prevent this? If so, how to do it?


    Not cleanly. There's a few examples of wrapped loads that allow you to
    load into a random namespace; I've done one myself as a theoretical
    example.

    Ultimately, though, this isn't the way that Ruby was meant to be used.

    What problem are you trying to solve? There might be another way.

    -austin
    --=20
    Austin Ziegler *
    * Alternate:
     
    Austin Ziegler, Jul 2, 2005
    #2
    1. Advertising

  3. On Sat, 02 Jul 2005 19:30:25 +0900, Austin Ziegler wrote:

    > Not cleanly. There's a few examples of wrapped loads that allow you to
    > load into a random namespace; I've done one myself as a theoretical
    > example.


    Where can I find those examples? I don't know what to search for.


    > What problem are you trying to solve? There might be another way.


    Well I want to write a FastCGI-Server in ruby. Depending on the queried
    website it should load the specific ruby-file based on some pattern.

    When I now have a file using GD for example, the loaded GD.so would hang
    around all the time. If I changed the file so that it wouldn't use GD
    anymore I would have to restart the server so that GD.so doesn't lie
    around in the memory forever (until the next reboot at least).

    Starting a new ruby-interpreter for every file isn't an option because it
    would take to long.

    Writing the FastCGI-Server in C isn't an option as well because when I
    initialize the ruby-interpreter (ruby_init()) a second time, all loaded
    files are still available to the interpreter. Otherwise I could have
    reinitialized the interpreter every few hours or so.

    Benjamin Hepp
     
    Benjamin Hepp, Jul 2, 2005
    #3
  4. This is what I do in Heretix:

    #
    # Packages is a container class for all package classes.
    # it is used to prevent the Package class names from polluting the global namespace
    #
    module Packages
    # Some package files need to 'require' other package files. The inline function
    # ensures that the inclusion occurs within the Packages module as load() and require()
    # both pollute the global namespace. If package files need to include other package
    # files (eg perl module needs perl.rb) they must use inline() rather than require()
    # or load(), which are removed to prevent their use (in the Package.load() function).
    #
    def Packages.inline(filename)
    Packages.module_eval(IO.read(filename),filename)
    end
    end

    def Package.load()

    # Load the package classes into the Packages namespace. load() and require()
    # both pollute the global namespace, so use some trickery instead. If package
    # files need to include other package files (eg perl module needs perl.rb)
    # they must use inline() rather than require() or load(), which are removed
    # so that relevant warnings are produced when package developers forget...
    #
    Kernel#remove_method :require
    Kernel#remove_method :load
    HERETIXDIR.cd {
    Dir.glob('core/packages/*.rb').each { |fn| Packages.inline(fn) }
    Dir.glob('contrib/packages/*.rb').each { |fn| Packages.inline(fn) }
    }

    ...
     
    Andrew Walrond, Jul 2, 2005
    #4
  5. On Sat, 02 Jul 2005 20:32:15 +0900, Andrew Walrond wrote:

    > This is what I do in Heretix:
    >
    > ...
    >


    Thanks so far.
    By overwriting Kernel#load and Kernel#require I could live with this
    method. The only problem I still have is how to load a .so file this way.
    I need something like module_eval(IO.read(filename)) for .so files. I
    guess this is impossible, right?

    Benjamin Hepp
     
    Benjamin Hepp, Jul 2, 2005
    #5
  6. Benjamin Hepp wrote:
    > Hello,
    >
    > I'm trying to build a module-mechanism in ruby so that I am able to load a
    > ruby-file without cluttering up the global namespace of the program.
    >
    > For example I want to be able to load a ruby-file, search for methods in
    > it, possibly execute one of them and then "unload" the file. When I call
    > Kernel#load with wrap = true, everything of the new file is put into an
    > anonymous Module, but every other file loaded in the new file itself is
    > put into the global namespace again.
    >
    > My questions:
    >
    > Is it at all possible to prevent this? If so, how to do it?
    > Can I access the anonymous Module in an easy manner?
    > How to delete/undefine a class or a method?


    A partial answer is the script library:

    http://raa.ruby-lang.org/project/script

    It cannot unload a library, and it cannot change what namespace .so
    extensions put their definitions in, but:

    * It wraps a loaded file (and its "local dependencies") in an instance
    of the Script class, which is a subclass of Module.

    * You can then assign this Script instance to a local var, constant, or
    whatever:

    script = Script.load("my-script.rb")

    * Top level method defs and constant defs in the wrapped file(s) can be
    accessed as methods or constants of this instance:

    script.foo()
    script::Foo

    * The "local dependencies" are defined to be any .rb files that can be
    found relative to the dir of the main script. This is handled by
    redefining #load and #require in the context of the Script instance. If
    the specified path is not found locally (or is a .so), then it falls
    back to Kernel#require.

    * There's also an autoloading feature.

    And there's another library to do this kind of thing:

    http://codeforpeople.com/lib/ruby/dynaload/
     
    Joel VanderWerf, Jul 2, 2005
    #6
  7. Benjamin Hepp

    Ara.T.Howard Guest

    On Sat, 2 Jul 2005, Benjamin Hepp wrote:

    > Hello,
    >
    > I'm trying to build a module-mechanism in ruby so that I am able to load a
    > ruby-file without cluttering up the global namespace of the program.
    >
    > For example I want to be able to load a ruby-file, search for methods in
    > it, possibly execute one of them and then "unload" the file. When I call
    > Kernel#load with wrap = true, everything of the new file is put into an
    > anonymous Module, but every other file loaded in the new file itself is
    > put into the global namespace again.
    >
    > My questions:
    >
    > Is it at all possible to prevent this? If so, how to do it?
    > Can I access the anonymous Module in an easy manner?
    > How to delete/undefine a class or a method?
    >
    > Thanks in advance
    > Benjamin Hepp


    i use a similar pattern for loading 'subscriptions' in our near-realtime
    system. a subscription is a dynamically loaded class for which and instance
    is created and then it's run method is called. to support doing this without
    killing the global namespace i write this

    http://raa.ruby-lang.org/project/dynaload/

    it should be just what you are looking for.

    cheers.

    -a
    --
    ===============================================================================
    | email :: ara [dot] t [dot] howard [at] noaa [dot] gov
    | phone :: 303.497.6469
    | My religion is very simple. My religion is kindness.
    | --Tenzin Gyatso
    ===============================================================================
     
    Ara.T.Howard, Jul 2, 2005
    #7
  8. Benjamin Hepp <> wrote:
    > Hello,
    >
    > I'm trying to build a module-mechanism in ruby so that I am able to
    > load a ruby-file without cluttering up the global namespace of the
    > program.
    >
    > For example I want to be able to load a ruby-file, search for methods
    > in it, possibly execute one of them and then "unload" the file. When
    > I call Kernel#load with wrap = true, everything of the new file is
    > put into an anonymous Module, but every other file loaded in the new
    > file itself is put into the global namespace again.
    >
    > My questions:
    >
    > Is it at all possible to prevent this? If so, how to do it?
    > Can I access the anonymous Module in an easy manner?
    > How to delete/undefine a class or a method?
    >
    > Thanks in advance
    > Benjamin Hepp


    I wonder why noone mentioned Kernel#load so far:
    http://www.ruby-doc.org/core/classes/Kernel.html#M001744

    Did I overlook something?

    Kind regards

    robert
     
    Robert Klemme, Jul 3, 2005
    #8
  9. On Sunday 03 July 2005 13:45, Robert Klemme wrote:
    > Benjamin Hepp <> wrote:
    > > I call Kernel#load with wrap = true, everything of the new file is
    > > put into an anonymous Module, but every other file loaded in the new
    > > file itself is put into the global namespace again.


    WRT below, see above. Caffeine topup required, perhaps?

    ;)

    >
    > I wonder why noone mentioned Kernel#load so far:
    > http://www.ruby-doc.org/core/classes/Kernel.html#M001744
    >
    > Did I overlook something?
    >
    > Kind regards
    >
    > robert
     
    Andrew Walrond, Jul 3, 2005
    #9
  10. Andrew Walrond <> wrote:
    > On Sunday 03 July 2005 13:45, Robert Klemme wrote:
    >> Benjamin Hepp <> wrote:
    >>> I call Kernel#load with wrap = true, everything of the new file is
    >>> put into an anonymous Module, but every other file loaded in the new
    >>> file itself is put into the global namespace again.

    >
    > WRT below, see above. Caffeine topup required, perhaps?
    >
    > ;)


    Darn! I knew it had to be something trivial... :)

    robert

    >
    >>
    >> I wonder why noone mentioned Kernel#load so far:
    >> http://www.ruby-doc.org/core/classes/Kernel.html#M001744
    >>
    >> Did I overlook something?
    >>
    >> Kind regards
    >>
    >> robert
     
    Robert Klemme, Jul 3, 2005
    #10
  11. Hello,

    Thanks to all the replies.

    I will have to live with .so-files polluting my global namespace but the
    problem with .rb files is solved now by overwriting load and require.

    Greetings
    Benjamin Hepp
     
    Benjamin Hepp, Jul 3, 2005
    #11
    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. Èý¹â
    Replies:
    1
    Views:
    599
    William F. Robertson, Jr.
    Jul 29, 2003
  2. Replies:
    0
    Views:
    5,166
  3. Anonymous
    Replies:
    3
    Views:
    560
    Ron Natalie
    Aug 18, 2003
  4. Petter Reinholdtsen
    Replies:
    9
    Views:
    4,432
    Howard
    Nov 29, 2004
  5. Hagbard Celine
    Replies:
    17
    Views:
    215
    Joel VanderWerf
    Jul 14, 2010
Loading...

Share This Page