Skip to content

Commit

Permalink
Merge 94fbb3d into 1f542c3
Browse files Browse the repository at this point in the history
  • Loading branch information
stevehook committed Jan 19, 2016
2 parents 1f542c3 + 94fbb3d commit e857e62
Show file tree
Hide file tree
Showing 18 changed files with 279 additions and 18 deletions.
33 changes: 33 additions & 0 deletions lib/lotus/view/configuration.rb
Expand Up @@ -4,6 +4,7 @@
require 'lotus/utils/string'
require 'lotus/utils/load_paths'
require 'lotus/view/rendering/layout_finder'
require 'lotus/view/rendering/partial_templates_finder'

module Lotus
module View
Expand Down Expand Up @@ -39,6 +40,7 @@ class Configuration
attr_reader :views
attr_reader :layouts
attr_reader :modules
attr_reader :partials

# Return the original configuration of the framework instance associated
# with the given class.
Expand Down Expand Up @@ -418,9 +420,39 @@ def duplicate
def load!
views.each { |v| v.__send__(:load!) }
layouts.each { |l| l.__send__(:load!) }
load_partials!
freeze
end

# Load partials for each partial template file found under the
# given load paths
#
# @since x.x.x
# @api private
def load_partials!
Lotus::View::Rendering::PartialTemplatesFinder.new(self).find.each do |partial|
add_partial(partial)
end
end

# Load partials for each partial template file found under the
# given load paths
#
# @since x.x.x
# @api private
def find_partial(relative_partial_path, template_name, format)
partials_for_view = partials.has_key?(relative_partial_path) ? partials[relative_partial_path] : partials[template_name]
partials_for_view ? partials_for_view[format.to_sym] : nil
end

# Add a partial to the registry
#
# @since x.x.x
# @api private
def add_partial(partial)
@partials[partial.key][partial.format.to_sym] = partial.template
end

# Reset all the values to the defaults
#
# @since 0.2.0
Expand All @@ -429,6 +461,7 @@ def reset!
root DEFAULT_ROOT
default_encoding DEFAULT_ENCODING

@partials = Hash.new { |h, k| h[k] = Hash.new }
@views = Set.new
@layouts = Set.new
@load_paths = Utils::LoadPaths.new(root)
Expand Down
7 changes: 7 additions & 0 deletions lib/lotus/view/rendering/partial_file.rb
@@ -0,0 +1,7 @@
module Lotus
module View
module Rendering
PartialFile = Struct.new(:key, :format, :template)
end
end
end
21 changes: 13 additions & 8 deletions lib/lotus/view/rendering/partial_finder.rb
Expand Up @@ -23,9 +23,10 @@ class PartialFinder < TemplateFinder
PREFIX = '_'.freeze

# Find a template for a partial. Initially it will look for the
# partial template under the directory of the parent directory
# view template, if not found it will search recursivly from
# the view root.
# partial template in the framework configuration where it may
# already be cached. Failing that it will look under the
# directory of the parent directory view template, if not found
# it will search recursively from the view root.
#
# @return [Lotus::View::Template] the requested template
#
Expand All @@ -34,14 +35,18 @@ class PartialFinder < TemplateFinder
# @since 0.4.3
# @api private
def find
if path = partial_template_under_view_path
View::Template.new(path, @view.configuration.default_encoding)
else
super
end
conf = Lotus::View::Configuration.for(@view)
conf.find_partial(relative_partial_path, template_name, format)
end

protected

# @since x.x.x
# @api private
def relative_partial_path
[view_template_dir, template_name].join(separator)
end

# @since 0.4.3
# @api private
def partial_template_under_view_path
Expand Down
65 changes: 65 additions & 0 deletions lib/lotus/view/rendering/partial_templates_finder.rb
@@ -0,0 +1,65 @@
require 'lotus/view/template'
require 'lotus/view/rendering/partial_file'

module Lotus
module View
module Rendering
# Find partial templates in the file system
#
# @api private
# @since x.x.x
#
# @see View::Template
class PartialTemplatesFinder
# Search pattern for partial file names
#
# @api private
# @since x.x.x
PARTIAL_PATTERN = '_*'.freeze

attr_reader :configuration

# Initializes a new PartialTemplatesFinder
#
# @param configuration [Configuration] the configuration object
#
# @since x.x.x
def initialize(configuration)
@configuration = configuration
end

# Find partials under the given path
#
# @return [Array] array of PartialFinder objects
#
# @since x.x.x
def find
_find_partials(configuration.root).map do |template|
path_name = Pathname(template)
partial_path, partial_base_name = Pathname(template).relative_path_from(configuration.root).split
partial_base_parts = partial_base_name.to_s.split('.')
PartialFile.new(
"#{partial_path}#{::File::SEPARATOR}#{partial_base_parts[0]}",
partial_base_parts[1],
View::Template.new(template, configuration.default_encoding))
end
end

private

# Find partial template file paths
#
# @param path [String] the path under which we should search for partials
#
# @return [Array] an array of strings for each matching partial template file found
#
# @since x.x.x
# @api private
def _find_partials(path)
Dir.glob("#{ [path, TemplatesFinder::RECURSIVE, PARTIAL_PATTERN].join(::File::SEPARATOR) }.#{TemplatesFinder::FORMAT}.#{TemplatesFinder::ENGINES}")
end
end
end
end
end

36 changes: 36 additions & 0 deletions test/fixtures.rb
Expand Up @@ -344,6 +344,42 @@ def raise_error
end
end

module App1
View = Lotus::View.duplicate(self) do
root __dir__ + '/fixtures/templates/app1/templates'
end

module Views
module Home
class Index
include App1::View
end
end
end
end

App1::View.load!

module App2
View = Lotus::View.duplicate(self) do
root __dir__ + '/fixtures/templates/app2/templates'
end

module Views
module Home
class Index
include App2::View
end

class Show
include App2::View
end
end
end
end

App2::View.load!

module Store
View = Lotus::View.duplicate(self)
View.extend Unloadable
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/templates/app1/templates/home/index.html.erb
@@ -0,0 +1 @@
<%= render partial: 'shared/app1_partial' %>
@@ -0,0 +1 @@
app 1 partial
1 change: 1 addition & 0 deletions test/fixtures/templates/app2/templates/home/index.html.erb
@@ -0,0 +1 @@
<%= render partial: 'shared/app2_partial' %>
1 change: 1 addition & 0 deletions test/fixtures/templates/app2/templates/home/show.html.erb
@@ -0,0 +1 @@
<%= render partial: 'shared/app1_partial' %>
@@ -0,0 +1 @@
app 2 partial
1 change: 1 addition & 0 deletions test/fixtures/templates/shared/_sidebar.json.erb
@@ -0,0 +1 @@
{ "sidebar": [] }
19 changes: 19 additions & 0 deletions test/integration/partial_test.rb
@@ -0,0 +1,19 @@
require 'test_helper'

describe 'Framework configuration' do
it "App1 can render a view containing one of it's own partials" do
rendered = App1::Views::Home::Index.render(format: :html)
rendered.must_include 'app 1 partial'
end

it "App2 can render a view containing one of it's own partials" do
rendered = App2::Views::Home::Index.render(format: :html)
rendered.must_include 'app 2 partial'
end

it "App2 cannot render a view containing a partial from App1" do
-> {
App2::Views::Home::Show.render(format: :html)
}.must_raise(Lotus::View::MissingTemplateError)
end
end
3 changes: 3 additions & 0 deletions test/layout_test.rb
@@ -1,6 +1,9 @@
require 'test_helper'
require 'reload_configuration_helper'

describe Lotus::Layout do
reload_configuration!

describe 'rendering from layout' do
it 'renders partial' do
rendered = IndexView.render(format: :html)
Expand Down
18 changes: 15 additions & 3 deletions test/load_test.rb
Expand Up @@ -2,9 +2,21 @@

describe Lotus::View do
describe '.load!' do
# before do
# Lotus::View.load!
# end
before do
Lotus::View.unload!
Lotus::View.class_eval do
configure do
root Pathname.new __dir__ + '/fixtures/templates'
end
end

Lotus::View.load!
end

it 'partials must be included in the framework configuration registry but not copied to individual view configurations' do
Lotus::View.configuration.partials.keys.must_include('shared/_sidebar')
Articles::Show.configuration.partials.keys.wont_include('shared/_sidebar')
end

# it 'freezes .layout for all the views' do
# AppView.layout.frozen?.must_equal true
Expand Down
28 changes: 25 additions & 3 deletions test/partial_finder_test.rb
@@ -1,11 +1,33 @@
require 'test_helper'
require 'reload_configuration_helper'

describe Lotus::View::Rendering::PartialFinder do
it 'finds the correct partial' do
reload_configuration!

it 'finds the correct partial in the same directory as the parent view' do
partial_finder = Lotus::View::Rendering::PartialFinder.new(Organisations::OrderTemplates::Action, partial: 'partial', format: 'html')
partial_finder.find.render(format: 'html').must_match 'Order Template Partial'
partial_finder.find.render({}).must_match 'Order Template Partial'

partial_finder = Lotus::View::Rendering::PartialFinder.new(Organisations::Action, partial: 'partial', format: 'html')
partial_finder.find.render(format: 'html').must_match 'Organisation Partial'
partial_finder.find.render({}).must_match 'Organisation Partial'
end

it 'finds the correct partial in a different directory to the parent view' do
partial_finder = Lotus::View::Rendering::PartialFinder.new(Organisations::OrderTemplates::Action, partial: 'shared/sidebar', format: 'html')
partial_finder.find.render({}).must_match '<div id="sidebar"></div>'
end

it 'finds the correct partial with a different format' do
partial_finder = Lotus::View::Rendering::PartialFinder.new(Organisations::OrderTemplates::Action, partial: 'shared/sidebar', format: 'json')
partial_finder.find.render({}).must_match '{ "sidebar": [] }'
end

it 'finds the correct partial from the cache rather than reading from the file system' do
partial_finder = Lotus::View::Rendering::PartialFinder.new(Organisations::OrderTemplates::Action, partial: 'partial', format: 'html')
partial_finder.find.wont_be_nil
partial_finder = Lotus::View::Rendering::PartialFinder.new(Organisations::OrderTemplates::Action, partial: 'shared/sidebar', format: 'html')
partial_finder.find.wont_be_nil
partial_finder = Lotus::View::Rendering::PartialFinder.new(Organisations::OrderTemplates::Action, partial: 'shared/sidebar', format: 'json')
partial_finder.find.wont_be_nil
end
end
14 changes: 14 additions & 0 deletions test/reload_configuration_helper.rb
@@ -0,0 +1,14 @@
class Minitest::Spec
def self.reload_configuration!
before do
Lotus::View.unload!
Lotus::View.class_eval do
configure do
root Pathname.new __dir__ + '/fixtures/templates'
end
end

Lotus::View.load!
end
end
end
3 changes: 3 additions & 0 deletions test/rendering_test.rb
@@ -1,7 +1,10 @@
require 'test_helper'
require 'reload_configuration_helper'
require 'ostruct'

describe Lotus::View do
reload_configuration!

describe 'rendering' do
it 'renders a template' do
HelloWorldView.render(format: :html).must_include %(<h1>Hello, World!</h1>)
Expand Down

0 comments on commit e857e62

Please sign in to comment.