So it does appear that the ActionController::Rendering module does
include AbstractController::Rendering, which means a call to super in
the render method of  ActionController::Rendering will in turn call
the render method of  AbstractController::Rendering. What makes this
somewhat confusing is that ActionController::Rendering is included in
ActionController::Base, but  AbstractController::Rendering is included
in ActionController::Base as well. Yet  AbstractController::Rendering
is also included in ActionController::Rendering. Wouldn't
AbstractController::Rendering being included
ActionController::Rendering and the fact that
ActionController::Rendering is included in ActionController::Base make
AbstractController::Rendering being included in ActionController::Base
redundant?

On Sep 17, 9:04 pm, John Merlino <stoici...@aol.com> 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?

-- 
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