Yep:

1.9.3p0 :005 > module B
1.9.3p0 :006?>   def name
1.9.3p0 :007?>     puts 'b module'
1.9.3p0 :008?>     end
1.9.3p0 :009?>   end
 => nil
1.9.3p0 :010 > module C
1.9.3p0 :011?>   def name
1.9.3p0 :012?>     puts 'c module'
1.9.3p0 :013?>     end
1.9.3p0 :014?>   end
 => nil
1.9.3p0 :015 > class A
1.9.3p0 :016?>   include B
1.9.3p0 :017?>   include C
1.9.3p0 :018?>   end
 => A
1.9.3p0 :019 > A.new.name
c module
 => nil

On Sep 18, 9:14 am, Matt Jones <al2o...@gmail.com> wrote:
> On Monday, 17 September 2012 21:04:58 UTC-4, John Merlino wrote:
>
> > In Ruby, classes are never closed: you can always add methods to an
> > existing class. This applies to the classes you write as well as the
> > standard, built-in classes. All you have to do is open up a class
> > definition for an existing class, and the new contents you specify
> > will be added to whatever's there. In the same regard, if module is
> > used with the name of a pre-existing module that module is re-opened.
> > If a method is defined in a re-opened module with the same name as a
> > pre-existing method in the same module the old method is overwritten
> > with the new. And, of course, modules can be made immutable,
> > effectively preventing them from being reopened by freezing the module
> > object. Frozen modules raise RuntimeErrors when methods are defined,
> > or variables manipulated, in their context.
>
> > When you include a module in a class, without a prefix (prefix meaning
> > something like this: AbstractController::Layouts), then ruby searches
> > for the module of that name within the scope of the current module
> > wrapping the class that the include was called in.
>
> > So, for example:
>
> > module ActionController
> >   class Base
> >     include Rendering
>
> > Since we "include Rendering" within the scope of the Base class
> > object, ruby first looksup the constant Rendering, that is, looking
> > for a module named Rendering in the ActionController namespace, since
> > that is the namesapce that Base is defined in???
>
> > Well, ActionController module does define a module named Rendering:
>
> > module ActionController
> >   module Rendering
> >      def render(*args)
> >       raise ::AbstractController::DoubleRenderError if response_body
> >       super
> >       self.content_type ||= Mime[lookup_context.rendered_format].to_s
> >       response_body
> >     end
>
> > So now the method render(*args) is included in the Base class as an
> > instance method. So when we call, for example, (hypothetically)
> > ActionView::Base.new.render :action => "my_action", :layout => false,
> > ActionView::Base is instantiated and we invoke the render instance
> > method, and since no render method is declared in the Base class
> > context, ruby scope chain does lookup into the module Rendering and
> > finds the method so calls it. Now, as you may know, it's possible to
> > pass multiple kinds of arguments to render, depending on whether you
> > want to render a template or a partial or file, etc. The * syntax does
> > the job here, allowing you vary the number of arguments passed. It
> > checks if there is already a response to the request, and raises an
> > Exception, if so. Otherwise, it calls super.
>
> > During this super call, I got a little confused. In
> > ActionController::Base, there is another module included called
> > AbstractController::Layouts. Layouts in turn includes a module called
> > Rendering. Since there is a Rendering module within the
> > AbstractController namespace, it is found, and it indeed contains a
> > method called render.
>
> >    def render(*args, &block)
> >       options = _normalize_render(*args, &block)
> >       self.response_body = render_to_body(options)
> >     end
>
> > And because render is included in Layouts, it's included as an
> > instance method, and because Layouts was included in
> > ActionController::Base, that render method utlimately makes its way up
> > to the Base class. Now we have two modules
> > (ActionController::Rendering and AbstractController::Rendering that
> > are including this method into Base. So why doesn't one of them get
> > overwritten? Why does the call to super work?
>
> The modules aren't "included" exactly - they're just added to the list of
> ancestors (try ActionController::Base.ancestors for an eyeful) where
> methods are looked up. Modules included later in the source are "higher" on
> the list (similar to subclass methods vs. base class methods) and calling
> 'super' simply specifies that the *next* available method up the chain
> should be called. This works (as of recent Rails versions) for generated
> methods as well:
>
> class SomeModel < ActiveRecord::Base
>   has_many :wats
>
>   def wats
>     # calling 'super' here hits the generated accessor from has_many
>   end
> end
>
> There's one additional wrinkle for many of the modules in Rails itself -
> many of them are extended with ActiveSupport::Concern, which tidies a bunch
> of things up and (most relevant here) changes the semantics of "include
> SomeOtherModule". See this article for more:
>
> http://opensoul.org/blog/archives/2011/02/07/concerning-activesupport...
>
> --Matt Jones

-- 
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@googlegroups.com.
To unsubscribe from this group, send email to 
rubyonrails-talk+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to