ms
2011-Dec-10 22:51 UTC
This modules thing somehow really does not work for me, please help.
Hey, thank you in advance for reading this post. I struggle with modularization / packaging / name spacing (however you want to call it) via ruby modules. I have the feeling that somehow rails is responsible for the problems I am facing. I hope, you can help me. Here''s an example to demonstrate more exactly what I mean: module Storage module Administration def self.do_something() # .. omitted end end end This does sometimes work under the rails console (development mode), most of the time I get: ruby-1.9.2-p290 :004 > Storage::Administration.do_something() NoMethodError: undefined method `do_something'' for Storage::Administration:Module This one here works more often (but not always): module Storage::Administration def self.do_something() # .. omitted end end What''s about the constant resolution operator (::)? As far as I know it is only allowed to reference constants (like module or class names), but not directly in definitions (module X::Y::Z). As I know it from pure ruby the first example should do it. You just nest the modules as you need and simply reopen a module if you want to extend it. So, the contents of my ruby files used for this example: "storage.rb" file (in a directory called "storage"): module Storage end And my "administration.rb" (in a subdirectory of "storage" called "administration"): module Storage module Administration # .. omitted end end OR (as I also tried) module Storage::Administration # .. omitted end What am I doing wrong? Why can''t rails (console, runner, etc.) access my static method _all the time_? Thank you very much for any suggestions! ms -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Peter Vandenabeele
2011-Dec-10 23:23 UTC
Re: This modules thing somehow really does not work for me, please help.
On Sat, Dec 10, 2011 at 11:51 PM, ms <ms-cGBD8117FJM@public.gmane.org> wrote:> Hey, > > thank you in advance for reading this post. I struggle with > modularization / packaging / name spacing (however you want to call > it) via ruby modules. I have the feeling that somehow rails is > responsible for the problems I am facing. I hope, you can help me. > > Here''s an example to demonstrate more exactly what I mean: > > module Storage > module Administration > > def self.do_something() > # .. omitted > end > > end > end > > This does sometimes work under the rails console (development mode), > most of the time I get: > > ruby-1.9.2-p290 :004 > Storage::Administration.do_something() > NoMethodError: undefined method `do_something'' for > Storage::Administration:Module > > This one here works more often (but not always): > > module Storage::Administration > > def self.do_something() > # .. omitted > end > > end > > What''s about the constant resolution operator (::)? As far as I know > it is only allowed to reference constants (like module or class > names), but not directly in definitions (module X::Y::Z). > > As I know it from pure ruby the first example should do it. You just > nest the modules as you need and simply reopen a module if you want to > extend it. > > So, the contents of my ruby files used for this example: > > "storage.rb" file (in a directory called "storage"): > > module Storage > end > > And my "administration.rb" (in a subdirectory of "storage" called > "administration"): > > module Storage > module Administration > > # .. omitted > > end > end > > OR (as I also tried) > > module Storage::Administration > > # .. omitted > > end > > What am I doing wrong? Why can''t rails (console, runner, etc.) access > my static method _all the time_? > > Thank you very much for any suggestions! >Under which directory exactly are you saving these files ? Which version of rails? If you use files under /lib, this may help (since recent versions of Rails, files under lib are not by default auto-loaded). # Custom directories with classes and modules you want to be autoloadable. config.autoload_paths += %W(#{config.root}/lib) config.autoload_paths += Dir["#{config.root}/lib/**/"] to understand the issue, I suggest you try step by step> Storage > Storage::Administration > Storage::Administration.functionto see how far it works and where exactly it breaks. This code below works reliably in Rails 3.1.x $ cat lib/storage/administration.rb module Storage module Administration def self.foo "foo" end end end $ rails c Loading development environment (Rails 3.1.3) 001:0> Storage => Storage 002:0> Storage::Administration => Storage::Administration 003:0> Storage::Administration.foo => "foo" 004:0> quit $ rgrep -i autoload config/application.rb # Custom directories with classes and modules you want to be autoloadable. config.autoload_paths += %W(#{config.root}/lib) config.autoload_paths += Dir["#{config.root}/lib/**/"] I would expect this code to be reliable on your side as well. HTH, Peter -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Frederick Cheung
2011-Dec-11 14:04 UTC
Re: This modules thing somehow really does not work for me, please help.
On 10 Dec 2011, at 22:51, ms <ms-cGBD8117FJM@public.gmane.org> wrote:> Hey, > > thank you in advance for reading this post. I struggle with > modularization / packaging / name spacing (however you want to call > it) via ruby modules. I have the feeling that somehow rails is > responsible for the problems I am facing. I hope, you can help me. >It sounds like the issue is with rails'' autoloading system> > What''s about the constant resolution operator (::)? As far as I know > it is only allowed to reference constants (like module or class > names), but not directly in definitions (module X::Y::Z). >module X::Y::Z is fine, but requires that X::Y already exists, whereas module X module Y module Z end end end Doesn''t. This also means that in the first case rails will look (via const_missing) for X::Y (in x/y.rb) whereas in the second case it won''t. If in x/y.rb you added some methods to Y and x/y.rb had never been loaded but z.rb had been then X::Y would still exist because of z.rb, but those methods from y.rb wouldn''t.> As I know it from pure ruby the first example should do it. You just > nest the modules as you need and simply reopen a module if you want to > extend it. > > So, the contents of my ruby files used for this example: > > "storage.rb" file (in a directory called "storage"): > > module Storage > endActually, rails would expect to find Storage in storage.rb at the top level, ie not in the storage folder> > And my "administration.rb" (in a subdirectory of "storage" called > "administration"): > > module Storage > module Administration > > # .. omitted > > end > end > > OR (as I also tried) > > module Storage::Administration > > # .. omitted > > endDitto, rails expects to find Storage::Administration in storage/administration.rb> What am I doing wrong? Why can''t rails (console, runner, etc.) access > my static method _all the time_? >Probably a combination of not putting things quite in the right place and using the module X module Y end end style, which doesn''t force rails to load x.rb, leading to different behaviour depending on whether you reference X before X::Y or the other way around. Fred> Thank you very much for any suggestions! > ms > > -- > You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. > To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. > For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en. >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Peter Vandenabeele
2011-Dec-11 18:10 UTC
Re: This modules thing somehow really does not work for me, please help.
On Sun, Dec 11, 2011 at 3:04 PM, Frederick Cheung < frederick.cheung-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > On 10 Dec 2011, at 22:51, ms <ms-cGBD8117FJM@public.gmane.org> wrote: > > > Hey, > > > > thank you in advance for reading this post. I struggle with > > modularization / packaging / name spacing (however you want to call > > it) via ruby modules. I have the feeling that somehow rails is > > responsible for the problems I am facing. I hope, you can help me. > > > > It sounds like the issue is with rails'' autoloading system > > > > > What''s about the constant resolution operator (::)? As far as I know > > it is only allowed to reference constants (like module or class > > names), but not directly in definitions (module X::Y::Z). > > > module X::Y::Z is fine, but requires that X::Y already exists, whereas > > module X > module Y > module Z > end > end > end > > Doesn''t. This also means that in the first case rails will look (via > const_missing) for X::Y (in x/y.rb) whereas in the second case it won''t. If > in x/y.rb you added some methods to Y and x/y.rb had never been loaded but > z.rb had been then X::Y would still exist because of z.rb, but those > methods from y.rb wouldn''t. >Thanks for the very interesting explanation. If I understand your reasoning correctly, the logic would be that in the cases with separate module definitions: 1) module X::Y::Z is loaded from the file ../lib/x/y/z.rb 2) this implicitely also defines the constant X::Y (based solely on information in file ../lib/x/y/z.rb and not trying to read ../lib/x/y.rb) 3) when X::Y is used later on, it is never really loaded from the file ../lib/x/y.rb , so what is defined there can be mysteriously missing (depending on the order modules where loaded). However, I could not produce this behavior as I understood it. As a test, I made 2 implementations of the module in ./lib/x/y/z.rb In both cases I have in ../lib/x/y.rb .../lib/x$ cat y.rb puts "loading module X / module Y in file ../lib/x/y.rb" module X module Y end end Test 1: separate module definitions =========================== .../lib/x/y$ cat z.rb module X module Y module Z def self.foo "Z.foo" end end end end Results: $ rails c Loading development environment (Rails 3.1.3) 001:0> ActiveSupport::Dependencies.logger = Rails.logger #=> <...> 002:0> ActiveSupport::Dependencies.log_activity=true #=> true 003:0> X::Y::Z loading module X / module Y in file ../lib/x/y.rb => X::Y::Z in logfile: Dependencies: called load_missing_constant(Object, :X) Dependencies: called load_missing_constant(X, :Y) Dependencies: called require_or_load(".../lib/x/y.rb", nil) Dependencies: loading .../lib/x/y Dependencies: called load_file(".../lib/x/y.rb", ["X::Y", "Y"]) Dependencies: called new_constants_in("X", :Object) Dependencies: New constants: X::Y Dependencies: loading .../lib/x/y.rb defined X::Y Dependencies: called load_missing_constant(X::Y, :Z) Dependencies: called require_or_load(".../lib/x/y/z.rb", nil) Dependencies: loading .../lib/x/y/z Dependencies: called load_file(".../lib/x/y/z.rb", ["X::Y::Z", "Y::Z", "Z"]) Dependencies: called new_constants_in("X::Y", "Y", :Object) Dependencies: New constants: X::Y::Z Dependencies: loading .../lib/x/y/z.rb defined X::Y::Z Test 2: (in 1 direct line module X::Y::Z) ============================ .../lib/x/y$ cat z.rb module X::Y::Z def self.foo "Z.foo" end end Results: $ rails c Loading development environment (Rails 3.1.3) 001:0> ActiveSupport::Dependencies.logger = Rails.logger #=> <...> 002:0> ActiveSupport::Dependencies.log_activity=true #=> true 003:0> X::Y::Z loading module X / module Y in file ../lib/x/y.rb => X::Y::Z In logifle: Dependencies: called load_missing_constant(Object, :X) Dependencies: called load_missing_constant(X, :Y) Dependencies: called require_or_load(".../lib/x/y.rb", nil) Dependencies: loading .../lib/x/y Dependencies: called load_file(".../lib/x/y.rb", ["X::Y", "Y"]) Dependencies: called new_constants_in("X", :Object) Dependencies: New constants: X::Y Dependencies: loading .../lib/x/y.rb defined X::Y Dependencies: called load_missing_constant(X::Y, :Z) Dependencies: called require_or_load(".../lib/x/y/z.rb", nil) Dependencies: loading .../lib/x/y/z Dependencies: called load_file(".../lib/x/y/z.rb", ["X::Y::Z", "Y::Z", "Z"]) Dependencies: called new_constants_in("X::Y", "Y", :Object) Dependencies: New constants: X::Y::Z Dependencies: loading .../lib/x/y/z.rb defined X::Y::Z So, my experiments seem to suggest that in both cases that I tried, there is an explicit order where all intermediate modules are loaded in turn (with load_missing_constants), even if only the deepest module would be strictly required to evaluate X::Y::Z Could you show an example of where the problem you described occurs. Or maybe this behavior has changed recently? Thanks, Peter -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Frederick Cheung
2011-Dec-11 19:30 UTC
Re: This modules thing somehow really does not work for me, please help.
On Dec 11, 6:10 pm, Peter Vandenabeele <pe...-jNuWw7i2w7syMbTcgqFhxg@public.gmane.org> wrote:> So, my experiments seem to suggest that in both cases > that I tried, there is an explicit order where all intermediate > modules are loaded in turn (with load_missing_constants), > even if only the deepest module would be strictly required to > evaluate X::Y::Z > > Could you show an example of where the problem you described > occurs. Or maybe this behavior has changed recently?Yeah I mixed things up a bit there as well as slightly mis- remembering. if you do things as rails expects, and rely entirely on the const_missing hooks then either way works. but if you deviate from that then things are different. For example if z.rb is module X module Y module Z end end end and you do require_dependency ''x/y/z'' then x/y.rb won''t be loaded but if you do module X::Y::Z end then it will. I guess the point I was trying to make was that if ruby ends up reading z.rb then using module X::Y::Z guarantees that x.rb and x/y.rb will be read, but the other form doesn''t, although the usual scenarios would mean that x.rb and x/y.rb would have been read earlier on anyway. Fred -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Peter Vandenabeele
2011-Dec-11 21:36 UTC
Re: Re: This modules thing somehow really does not work for me, please help.
On Sun, Dec 11, 2011 at 8:30 PM, Frederick Cheung < frederick.cheung-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> On Dec 11, 6:10 pm, Peter Vandenabeele <pe...-jNuWw7i2w7syMbTcgqFhxg@public.gmane.org> wrote: > > > So, my experiments seem to suggest that in both cases > > that I tried, there is an explicit order where all intermediate > > modules are loaded in turn (with load_missing_constants), > > even if only the deepest module would be strictly required to > > evaluate X::Y::Z > > > > Could you show an example of where the problem you described > > occurs. Or maybe this behavior has changed recently? > > Yeah I mixed things up a bit there as well as slightly mis- > remembering. if you do things as rails expects, and rely entirely on > the const_missing hooks then either way works. but if you deviate from > that then things are different. > > For example if z.rb is > > module X > module Y > module Z > end > end > end > > and you do require_dependency ''x/y/z'' then x/y.rb won''t be loaded > > but if you do > > module X::Y::Z > end > > then it will. > > I guess the point I was trying to make was that if ruby ends up > reading z.rb then using module X::Y::Z guarantees that x.rb and x/y.rb > will be read, but the other form doesn''t, although the usual scenarios > would mean that x.rb and x/y.rb would have been read earlier on > anyway. >Thanks for the additional info. I was now able to reproduce your point. .../lib/x/y$ cat z.rb module X module Y module Z def self.foo "Z.foo" end end end end and using ''require_dependency'' the result the functionality in the file x/y.rb is not loaded when loading module Z: $ rails c Loading development environment (Rails 3.1.3) 001:0> ActiveSupport::Dependencies.logger = Rails.logger 002:0> ActiveSupport::Dependencies.log_activity=true 003:0> require_dependency ''x/y/z'' => true # In log this gives: Dependencies: called require_or_load(".../lib/x/y/z.rb", nil) Dependencies: loading .../lib/x/y/z Dependencies: called load_file(".../lib/x/y/z.rb", ["X::Y::Z", "Y::Z", "Z"]) Dependencies: called new_constants_in("X::Y", "Y", :Object) Dependencies: New constants: X::Y::Z, X Dependencies: loading .../lib/x/y/z.rb defined X::Y::Z, X # X::Y::Z is defined as expected # X is also defined (that is an ancestor) # X::Y and Y are not defined (while these are ancestors too) 004:0> X::Y.foo NoMethodError: undefined method `foo'' for X::Y:Module from (irb):4 from .../gems/railties-3.1.3/lib/rails/commands/console.rb:45:in `start'' from .../gems/railties-3.1.3/lib/rails/commands/console.rb:8:in `start'' from .../gems/railties-3.1.3/lib/rails/commands.rb:40:in `<top (required)>'' from script/rails:6:in `require'' from script/rails:6:in `<main>'' 005:0> require_dependency ''x/y'' loading module X / module Y in file ../lib/x/y.rb => true # This shows in the log: Dependencies: called require_or_load(".../lib/x/y.rb", nil) Dependencies: loading .../lib/x/y Dependencies: called load_file(".../lib/x/y.rb", ["X::Y", "Y"]) Dependencies: called new_constants_in("X", :Object) Dependencies: New constants: 006:0> X::Y.foo => "Y.foo" With the version: /lib/x/y$ cat z.rb module X::Y::Z def self.foo "Z.foo" end end The result is: $ rails c Loading development environment (Rails 3.1.3) 001:0> ActiveSupport::Dependencies.logger = Rails.logger 002:0> ActiveSupport::Dependencies.log_activity=true 003:0> require_dependency ''x/y/z'' loading module X / module Y in file ../lib/x/y.rb => true # log now shows a recursive resolution Dependencies: called require_or_load(".../lib/x/y/z.rb", nil) Dependencies: loading .../lib/x/y/z Dependencies: called load_file(".../lib/x/y/z.rb", ["X::Y::Z", "Y::Z", "Z"]) Dependencies: called new_constants_in("X::Y", "Y", :Object) Dependencies: called load_missing_constant(Object, :X) Dependencies: called load_missing_constant(X, :Y) Dependencies: called require_or_load(".../lib/x/y.rb", nil) Dependencies: loading .../lib/x/y Dependencies: called load_file(".../lib/x/y.rb", ["X::Y", "Y"]) Dependencies: called new_constants_in("X", :Object) Dependencies: New constants: X::Y Dependencies: loading .../lib/x/y.rb defined X::Y Dependencies: New constants: X::Y::Z, X Dependencies: loading .../lib/x/y/z.rb defined X::Y::Z, X 004:0> X::Y.foo => "Y.foo" Thanks again, Peter -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.