|
|
|
|
||||||
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
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).n ew 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. |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
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-forum.com/. |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
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-forum.com/. |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
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).n ew > 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 |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
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. |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
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 s (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-forum.com/. |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
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-forum.com/. |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
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-forum.com/. |
|
|
|
#9 |
|
Messages: n/a
Hébergeur: |
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. |
|
|
|
#10 |
|
Messages: n/a
Hébergeur: |
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/ -- it is not enough to be compassionate. you must act. h.h. the 14th dalai lama |
|
|
|
#11 |
|
Messages: n/a
Hébergeur: |
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 ![]() |
|
|
|
#12 |
|
Messages: n/a
Hébergeur: |
On 11/5/07, ara.t.howard <ara.t.howard@gmail.com> wrote:
> 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 > You can also use the predefined constant TOPLEVEL_BINDING, e.g. object = eval 'File::Stat', TOPLEVEL_BINDING Regards, Sean |
|
|
|
#13 |
|
Messages: n/a
Hébergeur: |
On Nov 5, 2007, at 4:20 PM, ara.t.howard wrote:
> 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. 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 |
|
|
|
#14 |
|
Messages: n/a
Hébergeur: |
On Nov 5, 2007, at 3:50 PM, Morton Goldberg 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/ -- we can deny everything, except that we have the possibility of being better. simply reflect on that. h.h. the 14th dalai lama |
|
|
|
#15 |
|
Messages: n/a
Hébergeur: |
On Nov 5, 2007, at 3:50 PM, Morton Goldberg wrote: > but I can't figure out what it is. So please explain. laziness ;-) sorry. a @ http://codeforpeople.com/ -- we can deny everything, except that we have the possibility of being better. simply reflect on that. h.h. the 14th dalai lama |
|
|
|
#16 |
|
Messages: n/a
Hébergeur: |
Sean O'halpin wrote:
> 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'). > ... 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 -- Posted via http://www.ruby-forum.com/. |
|
|
|
#17 |
|
Messages: n/a
Hébergeur: |
In article
<3736dd30711042349n7225229dw4af74110f2a52048@mail. gmail.com>, sean.ohalpin@gmail.com wrote: > 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).n ew > > 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] > 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 > __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 > __END__ > # output > Hi from #<MyPlugin:0xb7c25594>! > Hi from #<Plugins::AnotherPlugin:0xb7c23dfc>! -- 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 |
|
Messages: n/a
Hébergeur: |
In article <Misc-4BC90C.22022205112007@newsclstr03.news.prodigy.net >,
Miss Elaine Eos <Misc@your-pants.PlayNaked.com> 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 ! -- 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. |
|
|
|
#19 |
|
Messages: n/a
Hébergeur: |
On 11/5/07, 7stud -- <bbxx789_05ss@yahoo.com> wrote:
> >> 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 > 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 |
|
![]() |
| Outils de la discussion | |
|
|