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!
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? 
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? 
On 11/5/07, Miss Elaine E. [email protected] wrote:
to the middle line, I get
full of class-definition-files and, once at a time,
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
In article
[email protected],
[email protected] 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! 
Miss Elaine E. wrote:
In article
[email protected],
[email protected] 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
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
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.
On Nov 5, 11:43 am, [email protected] 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.
On 11/5/07, 7stud – [email protected] 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 
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://codeforpeople.com/
On 11/5/07, ara.t.howard [email protected] wrote:
object = eval ‘File::Stat’, Binding::Top
You can also use the predefined constant TOPLEVEL_BINDING, e.g.
object = eval ‘File::Stat’, TOPLEVEL_BINDING
Regards,
Sean
On Nov 5, 2007, at 4:20 PM, ara.t.howard wrote:
which, for some reason, routinely confounds people on the list…
2 cts.
You probably have a good reason for writing the above rather than the
simpler
eval('File::Stat', TOPLEVEL_BINDING) # => File::Stat
but I can’t figure out what it is. So please explain.
Regards, Morton
On Nov 5, 2007, at 3:50 PM, Morton G. wrote:
You probably have a good reason for writing the above rather than
the simpler
eval(‘File::Stat’, TOPLEVEL_BINDING) # => File::Stat
but I can’t figure out what it is. So please explain.
a) always forgetting what the constant is named
b) begin too lazy to look it when i was posting
TOPLEVEL_BINDING is, of course, the better way to go! 
sorry for any confusion caused by my laziness.
ps. i do wish the top level binding was part of the Binding class,
Binding.top, or something, because i can never remember where it
lives…
a @ http://codeforpeople.com/
On Nov 5, 2007, at 3:50 PM, Morton G. wrote:
but I can’t figure out what it is. So please explain.
laziness
sorry.
a @ http://codeforpeople.com/
Sean O’halpin wrote:
On 11/5/07, 7stud – [email protected] 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’).
… so are Module.const_get and Class.const_get:
class Dog
end
module Stuff
Greeting = “hello”
end
MyConst = 10
puts Module.const_get(“Dog”).new
puts Module.const_get(“Stuff”)::Greeting
puts Module.const_get(“MyConst”)
puts
puts Class.const_get(“Dog”).new
puts Class.const_get(“Stuff”)::Greeting
puts Class.const_get(“MyConst”)
–output:–
#Dog:0x251c0
hello
10
#Dog:0x25148
hello
10
In article [email protected],
Miss Elaine E. [email protected] wrote:
Ok, I tried your example, below, and it worked the same for me as for
you. But when I go back to my actual code, same problem. I don’t
follow what’s different about what your example is doing and what I’m
doing. Here are some differences:
- I’m running under rails. Can’t see how that should matter – this is
long before any of the rendering stuff, and no DB accesses. I’m just
triggering code in a controller. That’s all ruby, right?
It seems that my problems had to do with leaving rails (WEBrick) running
and changing my controller/plug-in files. Once I quit & restarted
WEBrick, everything started working just fine.
Not sure why – I though in the past that redefining objects worked
correctly.
Anyway, thank you much for your help!
In article
[email protected],
[email protected] wrote:
On 11/5/07, Miss Elaine E. [email protected] 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
[snip]
Ok, I tried your example, below, and it worked the same for me as for
you. But when I go back to my actual code, same problem. I don’t
follow what’s different about what your example is doing and what I’m
doing. Here are some differences:
-
I’m running under rails. Can’t see how that should matter – this is
long before any of the rendering stuff, and no DB accesses. I’m just
triggering code in a controller. That’s all ruby, right?
-
My program works like your example, below, except that it walks a
directory and does the trick for every file in it. So, rather than call
“myplugin.rb”, it walks the directory, finds my_plugin.rb, uses that as
a filename, converts to MyPlugin for class name, but the rest is the
same.
-
My actual plugin is a sub-class of a master-plugin. This is how I
guarantee the interface. (There’s probably a more Ruby-like way to do
this, but it’s what I know…) So myplugin is mildly complicated in
that my 1st line looks more like this:
class MyPlugin < MasterPlugin
But modifying the sample (below) to replicate that doesn’t seem to
impact it’s working-ness.
So I’m stuck trying to figure out how & where to trim back my original
to get it to act like the example. Does Rails actually matter?! Does
it matter if my require is inside a loop and/or inside another class (a
rails controller)?
The problem: I get
uninitialized constant MyPlugin
at the line with const_get().
[Example trimmed back to the minimal case that I’m using]
On 11/5/07, 7stud – [email protected] wrote:
end
puts Module.const_get(“MyConst”)
#Dog:0x25148
hello
10
Hi,
This illustrates what I mean:
Greeting = “goodbye”
class Module
Greeting = “hello”
end
class Class
Greeting = “hi!”
end
puts Module.const_get(“Greeting”)
puts Class.const_get(“Greeting”)
puts Object.const_get(“Greeting”)
puts eval( “Greeting”, TOPLEVEL_BINDING ) # for Ara 
–output–
hello
hi!
goodbye
goodbye
Regards,
Sean