From: Mike Papper Date: 2009-12-08T11:02:02+09:00 Subject: Re: Use of extend from within a Class Hi and thanks for explaining the helper method. I understand whats going on except for master_helper_module.module_eval -what is master_helper_module ? (Presumably it has the effect of "include ModuleName - but how that makes self.class.XYZ work is still not understood). ---------------- Back to the UrlWriter module... I did some tests and noticed that self.included is not called when a module is extended (versus included). For UrlWriter, this means that this code doesnt get executed: def self.included(base) #:nodoc: ActionController::Routing::Routes.install_helpers(base) base.mattr_accessor :default_url_options base.default_url_options ||= default_url_options end I changed my code to explicitly call that method after I extended, ala: def self.staticmethod extend ActionController::UrlWriter ActionController::UrlWriter.included(self) # the class self.default_url_options = {} # doesnt seem to do much but still this line from UrlWriter.url_for fails: self.class.default_url_options.merge(options) As you said, self.class refers to Class so I dont see how that line works when the module is included as a helper. Can you explain this?? Mike Rick Denatale wrote: > On Mon, Dec 7, 2009 at 4:26 PM, Mike Papper > wrote: >> helper but cannot really make any sense of it. > MyController < ActionController::Base > include UrlWriter # include not extend > end > > If you read the code in actionpack/lib/action_controller/helpers.rb it > really isn't that hard to see what's going on > > if in the controller you write say > > helper :url_writer > > then the helper method takes the case branch for a symbol. which is: > > file_name = arg.to_s.underscore + '_helper' > class_name = file_name.camelize > > begin > require_dependency(file_name) > rescue LoadError => load_error > requiree = / -- > (.*?)(\.rb)?$/.match(load_error.message).to_a[1] > if requiree == file_name > msg = "Missing helper file helpers/#{file_name}.rb" > raise LoadError.new(msg).copy_blame!(load_error) > else > raise > end > end > > add_template_helper(class_name.constantize) > > So it computes a file name from the argument, in this case > "url_writer.rb", and a class (actually a Module) name "UrlWriter" > > Then require dependency loads the file if necessary, and finally. > > class_name.constantize turns teh class name into the actual module, > and passes it as the argument to add_template_helper which is defined > above as: > > def add_template_helper(helper_module) #:nodoc: > master_helper_module.module_eval { include helper_module } > end > > So it is effectively the same thing as what I first wrote. > > -- > Rick DeNatale > > Blog: http://talklikeaduck.denhaven2.com/ > Twitter: http://twitter.com/RickDeNatale > WWR: http://www.workingwithrails.com/person/9021-rick-denatale > LinkedIn: http://www.linkedin.com/in/rickdenatale -- Posted via http://www.ruby-forum.com/.