require 'lotus/view/rendering/layout_registry' require 'lotus/view/rendering/view_finder' module Lotus module View module Rendering # Holds all the references of all the registered subclasses of a view. # We have one registry for each superclass view. # # @api private # @since 0.1.0 # # @see Lotus::View::Rendering::LayoutRegistry # @see Lotus::View::Rendering#registry # # @example # require 'lotus/view' # # module Articles # class Index # include Lotus::View # end # # class Show # include Lotus::View # end # # class JsonShow < Show # format :json # end # # class XmlShow < Show # format :xml # # def render # ArticleSerializer.new(article).to_xml # end # end # end # # # We have the following templates: # # # # * articles/index.html.erb # # * articles/index.atom.erb # # * articles/show.html.erb # # * articles/show.json.erb # # # One registry per superclass view # Articles::Index.send(:registry).object_id # => 70135342862240 # # Articles::Show.send(:registry).object_id # => 70135342110540 # Articles::XmlShow.send(:registry).object_id # => 70135342110540 # Articles::JsonShow.send(:registry).object_id # => 70135342110540 # # # # # It holds the references for all the templates and the views # Articles::Index.send(:registry).inspect # # => { :all => [Articles::Index, nil], # # :atom => [Articles::Index, #<Lotus::View::Template ... @file="/path/to/templates/articles/index.atom.erb"], # # :html => [Articles::Index, #<Lotus::View::Template ... @file="/path/to/templates/articles/index.html.erb"] } # # Articles::Show.send(:registry).inspect # # => { :all => [Articles::Show, nil], # # :html => [Articles::Show, #<Lotus::View::Template ... @file="/path/to/templates/articles/show.html.erb"], # # :json => [Articles::JsonShow, #<Lotus::View::Template ... @file="/path/to/templates/articles/show.json.erb"], # # :xml => [Articles::XmlShow, nil] } class Registry < LayoutRegistry # Default format for views without an explicit format. # # @api private # @since 0.1.0 # # @see Lotus::View::Dsl#format DEFAULT_FORMAT = :all # Returns the view for the given context. # # @param context [Hash] the rendering context # @option context [Symbol] :format the requested format # @param locals [Hash] the set of available objects # # @return [Lotus::View] the view associated with the given context # # @raise [Lotus::View::MissingFormatError] if the given context doesn't # have the :format key # # @api private # @since 0.1.0 # # @see Lotus::View::Rendering#render def resolve(context) view, template = fetch(format(context)) { self[DEFAULT_FORMAT] } view.new(template, context) end private def prepare! prepare_views! prepare_templates! end def prepare_views! views.each do |view| merge! view.format || DEFAULT_FORMAT => [ view, template_for(view) ] end end def prepare_templates! templates.each do |template| merge! template.format => [ view_for(template), template ] end end def views @view.subclasses + [ @view ] end def view_for(template) ViewFinder.new(@view).find(template) end def template_for(view) templates.find {|template| template.format == view.format } end end end end end