[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

[n00b] Reading a class-file and calling it at runtime.

Miss Elaine Eos

11/5/2007 1:48:00 AM

I'm trying to read-in a folder full of "plug-ins" and call each of them,
in turn. Once I get the class-name, I do something like:

require "#{PLUG_IN_DIR}/#{one_plugin}"
plugin_class=Object.const_get(plugin_class_name).new
plugin_class.some_method

I *thought* that require worked a bit like the C pre-processor
"include", in that it would read and execute the named file at that
point, thereby defining my class and its methods. However, when I get
to the middle line, I get

uninitialized constant PluginClassName

Since rails is mistaking my class-name for a constant, I'm guessing that
require didn't execute the way I think it does, so my class-name isn't
initialized.

....Or maybe I've completely mis-diagnosed the problem.

At any rate, can someone offer a suggestion for how to read a folder
full of class-definition-files and, once at a time,

* Execute the class definition, so that my app knows about it
* Instantiate an instance of the class (I think we have this part,
above)
* Call a method on that class (should just be able to say
"a_class.a_method", right?)

Thanks!

--
Please take off your pants or I won't read your e-mail.
I will not, no matter how "good" the deal, patronise any business which sends
unsolicited commercial e-mail or that advertises in discussion newsgroups.
18 Answers

Emmanuel Oga

11/5/2007 3:20:00 AM

0

I'm not sure what you are trying to acomplish... but here is a trick i
use when rails mess with my requires.

def require_relative *args
path= File.dirname(args.shift)
args.each { |arg| path= File.join(path, arg) }
require path
end

This will require the file with full file name. Now you can do

Dir[File.join(File.dirname(__FILE__), '/plugins/*.rb')].each do |file|
require_relative __FILE__, file
end

That loads every file of directory plugins. Now, if you named the files
according to rails convetions, ie:

my_class_name.rb for MyClassName class, you can do something like:

plugin_classes= []

Dir[File.join(File.dirname(__FILE__), '/plugins/*.rb')].each do |file|
require_relative __FILE__, file
name= File.basename(file)
plugin_classes << $1.camelize.constantize if name =~ /(.*)\.rb$/i
end

There... it sounds easy, no? :)
--
Posted via http://www.ruby-....

Emmanuel Oga

11/5/2007 3:22:00 AM

0

mmm i believe i messed up the things a bit, this should be the right
thing to do, if complex, anyway:

plugin_classes= []

Dir[File.join(File.dirname(__FILE__), '/plugins/*.rb')].each do |file|

file_name= File.basename(file)

require_relative __FILE__, 'plugins', file_name

plugin_classes << $1.camelize.constantize if file_name =~ /(.*)\.rb$/i
end

There, now it should work! :)


>
> plugin_classes= []
>
> Dir[File.join(File.dirname(__FILE__), '/plugins/*.rb')].each do |file|
> require_relative __FILE__, file
> name= File.basename(file)
> plugin_classes << $1.camelize.constantize if name =~ /(.*)\.rb$/i
> end
>
> There... it sounds easy, no? :)

--
Posted via http://www.ruby-....

Sean O'Halpin

11/5/2007 7:49:00 AM

0

On 11/5/07, Miss Elaine Eos <Misc@your-pants.playnaked.com> wrote:
> I'm trying to read-in a folder full of "plug-ins" and call each of them,
> in turn. Once I get the class-name, I do something like:
>
> require "#{PLUG_IN_DIR}/#{one_plugin}"
> plugin_class=Object.const_get(plugin_class_name).new
> plugin_class.some_method
>
> I *thought* that require worked a bit like the C pre-processor
> "include", in that it would read and execute the named file at that
> point, thereby defining my class and its methods. However, when I get
> to the middle line, I get
>
> uninitialized constant PluginClassName
>
> Since rails is mistaking my class-name for a constant, I'm guessing that
> require didn't execute the way I think it does, so my class-name isn't
> initialized.
>
> ...Or maybe I've completely mis-diagnosed the problem.
>
> At any rate, can someone offer a suggestion for how to read a folder
> full of class-definition-files and, once at a time,
>
> * Execute the class definition, so that my app knows about it
> * Instantiate an instance of the class (I think we have this part,
> above)
> * Call a method on that class (should just be able to say
> "a_class.a_method", right?)
>
> Thanks!
>
> --
> Please take off your pants or I won't read your e-mail.
> I will not, no matter how "good" the deal, patronise any business which sends
> unsolicited commercial e-mail or that advertises in discussion newsgroups.
>
>
Hi,

What you're doing here is right in principle. For example, in this code:

# ./myplugin.rb
class MyPlugin
def some_method
puts "Hi from #{self}!"
end
end

module Plugins
class AnotherPlugin
def some_method
puts "Hi from #{self}!"
end
end
end
__END__

# test-require-plugin.rb
one_plugin = "myplugin"
PLUG_IN_DIR = '.'
plugin_class_name = "MyPlugin"

require "#{PLUG_IN_DIR}/#{one_plugin}"
plugin_class = Object.const_get(plugin_class_name).new
plugin_class.some_method

plugin_class_name = "AnotherPlugin"
plugin_class = Plugins.const_get(plugin_class_name).new
plugin_class.some_method

# this will fail
plugin_class = Object.const_get(plugin_class_name).new
plugin_class.some_method

__END__
# output
Hi from #<MyPlugin:0xb7c25594>!
Hi from #<Plugins::AnotherPlugin:0xb7c23dfc>!
test-require-plugin.rb:14:in `const_get': uninitialized constant
AnotherPlugin (NameError)
from test-require-plugin.rb:14

only the last call to some_method fails. Have you checked that the
name of the class is correct or if you are defining your plugin class
within a module?

Regards,
Sean

Miss Elaine Eos

11/5/2007 3:12:00 PM

0

In article
<3736dd30711042349n7225229dw4af74110f2a52048@mail.gmail.com>,
sean.ohalpin@gmail.com wrote:

> only the last call to some_method fails. Have you checked that the
> name of the class is correct or if you are defining your plugin class
> within a module?

I am NOT using "module." I guess I need to go read-up on modules --
Thanks! :)

--
Please take off your pants or I won't read your e-mail.
I will not, no matter how "good" the deal, patronise any business which sends
unsolicited commercial e-mail or that advertises in discussion newsgroups.

7stud --

11/5/2007 6:30:00 PM

0

Miss Elaine Eos wrote:
> In article
> <3736dd30711042349n7225229dw4af74110f2a52048@mail.gmail.com>,
> sean.ohalpin@gmail.com wrote:
>
>> only the last call to some_method fails. Have you checked that the
>> name of the class is correct or if you are defining your plugin class
>> within a module?
>
> I am NOT using "module." I guess I need to go read-up on modules --
> Thanks! :)

Maybe you should post a simplified version of one of the files you are
requiring, e.g.

class Dog
def speak
puts "Woof woof"
end
end


As this example shows:

>Sean O'halpin wrote:
>
> # ./myplugin.rb
>
> class MyPlugin
> def some_method
> puts "Hi from #{self}!"
> end
> end
>
>---------------
>
> # test-require-plugin.rb
>
> one_plugin = "myplugin"
> PLUG_IN_DIR = '.'
> plugin_class_name = "MyPlugin"
>
> require "#{PLUG_IN_DIR}/#{one_plugin}"
> plugin_class = Object.const_get(plugin_class_name).new
> plugin_class.some_method
>
> # output
> Hi from #<MyPlugin:0xb7c25594>!

...you don't need to have your class inside a module to get your code to
work. But the rest of the example showed that IF your class definition
is inside a module, then you have to alter your syntax a little to
retrieve the class with const_get.

Here is another example if it helps (all files are in the current
directory):

#plugin.rb:

class Dog
def speak
puts "Woof woof"
end
end



#my_program.rb:

require 'plugin'

dog_class = Object.const_get("Dog")
dog = dog_class.new
dog.speak


--
Posted via http://www.ruby-....

7stud --

11/5/2007 6:44:00 PM

0

Sean O'halpin wrote:
>
> plugin_class = Object.const_get(plugin_class_name).new
>

I have a question about using Object as the receiver in the above line.
Is there any specific reason you are using Object? I find calling
const_get with Object very confusing because the Object class does not
define a const_get method--it's only tracking const_get through ruby's
extremely confusing circular inheritance:

Object <------+
| |
V |
Module |
--const_get |
|
| |
V |
Class ---------+

that const_get lands in Object. Since calling const_get with any of the
class names Object, Module, or Class seems to work, why not just use
Module or Class to call const_get? If no Modules are involved, which
seems to be the op's case, then Class would seem like the least
confusing name to call const_get with.

#plugin.rb:

class Dog
def speak
puts "Woof woof"
end
end

-----------

#my_program.rb:

require 'plugin'

dog_class = Class.const_get("Dog")
dog = dog_class.new
dog.speak

Of course calling const_get with Class might still result in some
confusion--looking up the methods for Class will not reveal a const_get
method.
--
Posted via http://www.ruby-....

7stud --

11/5/2007 6:57:00 PM

0

7stud -- wrote:
>it's only tracking const_get through ruby's
> extremely confusing circular inheritance:
>
> Object <------+
> | |
> V |
> Module |
> --const_get |
> |
> | |
> V |
> Class ---------+
>

This might be a clearer diagram:

Object
|
V
Module
--const_get

|
V
Class
|
V
Object (Object is a subclass of Class)


puts Class.kind_of?(Object)
-->true

puts Object.kind_of?(Class)
-->true

--
Posted via http://www.ruby-....

Phrogz

11/5/2007 7:43:00 PM

0

On Nov 5, 11:43 am, bbxx789_0...@yahoo.com wrote:
> Sean O'halpin wrote:
>
> > plugin_class = Object.const_get(plugin_class_name).new
>
> I have a question about using Object as the receiver in the above line.
> Is there any specific reason you are using Object?


> dog_class = Class.const_get("Dog")
> dog = dog_class.new
> dog.speak
>
> Of course calling const_get with Class might still result in some
> confusion--looking up the methods for Class will not reveal a const_get
> method.

For me personally, having someone write Module.const_get versus
Class.const_get implies that the former will only return a Module
instance, and the latter would only return a Class instance. By using
Object.const_get you are clearly stating that there is no guarantee as
to what type of object the supplied constant points to.

ara.t.howard

11/5/2007 9:21:00 PM

0


On Nov 5, 2007, at 12:45 PM, Phrogz wrote:

> For me personally, having someone write Module.const_get versus
> Class.const_get implies that the former will only return a Module
> instance, and the latter would only return a Class instance. By using
> Object.const_get you are clearly stating that there is no guarantee as
> to what type of object the supplied constant points to.
>

i prefer Object.const_get too, although for different reasons: it
*should* be well known by ruby programmers that the 'top' context is
the Object instances called 'main'. another approach, suitable for
some limited situations is simply

object = eval name, Binding::Top

BEGIN{
Binding::Top = binding
}

which is less safe, of course, but works with effort for cases like

object = eval 'File::Stat', Binding::Top

which, for some reason, routinely confounds people on the list...

2 cts.

a @ http://codeforp...
--
it is not enough to be compassionate. you must act.
h.h. the 14th dalai lama




Sean O'Halpin

11/5/2007 10:37:00 PM

0

On 11/5/07, 7stud -- <bbxx789_05ss@yahoo.com> wrote:
> Sean O'halpin wrote:
> >
> > plugin_class = Object.const_get(plugin_class_name).new
> >
>
> I have a question about using Object as the receiver in the above line.
> Is there any specific reason you are using Object?

It's a way of looking up constants in the scope of the top level
binding (the special Object known as 'main').

Regards,
Sean

P.S. Thanks for clarifying my other post :)