Forum: Ruby on Rails ERB and Builder template engines shouldn't be so heavily wir

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
5f241b8cae62093f8888cfdb0895c60d?d=identicon&s=25 MiG (Guest)
on 2006-03-12 14:41
(Received via mailing list)
Problem:

1. ERB and Builder template engines are heavily wired in
ActionView::Base
2. Should be optional. If we use different engine - why load all their
stuff if not needed?
3. There are template engines which expect files in their own locations
and cache them in their own way. For instance a template engine may
store templates in a database. These engines don't need any central
source loader of files which they don't need, moreover of files which
don't exist. Files, which expects a file per an action.



Why is it problem for me?

I wrote a ViewController templating engine. ViewController is similar to
Controller - is just one file, a class, which controls views of all
actions.
It uses yaml data files from which loads data. It is real push-style
template engine.

app/views/foo/foo_view_controller.vcrb

class FooViewController < ActiveView::ViewController::Base

   def index
       return get( :body ) do |body|
          body.title = 'Homepage'
          body.time  = Time.now
          body.table do |table|
            @people.each do |person|
               table << get( :row, :name=>person.name,
:surname=>person.sn )
             end
          end
       end
   end

   def list
      return get( :body, :title=>'under construction', :time=>Time.now )
   end

end



Request:

More modularization. Template engines should be independent and
optional,
even ERB and Builder. Template engines should do source loading and
caching itself.



Solution:

1. The ActionView::Base should work just like a register / dispatcher
for
template engines.

2. Every template engine (including ERB and Builder) should be placed
inside the vendor directory.

3. Every template engine should have a base class
ActionView::Engines::EngineName with these methods:

self::template_exists?( render_options={} )
self::type  # return :rhtml, :rxml, :vcrb, etc.
initialize( action_view )
render( render_options={}, local_assigns={} )

4. Only used template engines will be then registered in environment.rb:

ActionView::Base.register_template_handler( 'erb' )
# does: require( "vendor/erb.rb" )

ActionView::Base.register_template_handler( 'view_controller' )
# does: require( "vendor/view_controller.rb" )

5. Each required file from vendor registers itself into
@@template_handlers.

@@template_handlers[ActionView::Handlers::Erb.type] =
ActionView::Handlers::Erb

@@template_handlers[ActionView::Handlers::ViewController.type] =
ActionView::Handlers::ViewController

6. If a request comes, the ActionView::Base will ask all registered
template handlers (in @@template_handlers), if the template specified by
render_options exists. If a handler responds true, the Base would create
an instance of that handler and call it's render method. That's all.
Every other stuff should be done by the handler.


How to do it:

1. Modularize ERB and Builder.

2. Don't pick the handler by the file extension, instead pass the
render_options to all registered handler's template_exists? and
check if some handler responds true.

3. File rendering would be processed this way (from ActionView::Base):

def render_file( render_options={}, local_assigns={} )
	@@template_handlers.each_value do |handler_class|
		if handler_class::template_exists?( render_options )
			return handler_class.new( render_options, local_assigns )
		end
	end
	raise 'no handler is able to render the file!'
end

Inline rendering would be processed this way (from ActionView::Base):

def render_inline( render_options={} )
	handler = @@template_handlers[ render_options[:type] ]
	return handler.render( render_options )
end

5. layout.rb would pass the 'content_for_layout' variable to
local_assigns of the render method (no special injecting into template).

6. rescue.rb shouldn't call render_file with a special file path.
Instead it should call render() with an option :error=>anError. This
would allow a handler to display the error. Then a handler which
responds to true will be used to display the error. Not only ERB can do
it.

7. For backward compatibility reasons and reasons when no other template
handler is registered, ERB will be loaded defaultly.


----------

I will public my ViewController after testing it a bit, I realized it is
really good :-)

Now I can run it only by hacking the ActionView::Base class but I don't
want to do it, I want ActionView to be more modularized to allow this
normal way.

What do you think about it? If you want, I can get more into the
ActionPack's code and work out the separation of ERB (with backward
compatibility, of course)


jan molic
This topic is locked and can not be replied to.