diff --git a/app/models/extensions/page/parse.rb b/app/models/extensions/page/parse.rb new file mode 100644 index 00000000..2018bccc --- /dev/null +++ b/app/models/extensions/page/parse.rb @@ -0,0 +1,40 @@ +module Models + module Extensions + module Page + module Parse + + extend ActiveSupport::Concern + + included do + field :serialized_template, :type => Binary + + before_validation :serialize_template + end + + module InstanceMethods + + def template + @template ||= Marshal.load(read_attribute(:serialized_template).to_s) rescue nil + end + + protected + + def serialize_template + if self.new_record? || self.raw_template_changed? + begin + @template = ::Liquid::Template.parse(self.raw_template, { :site => self.site }) + @template.root.context.clear + + self.serialized_template = BSON::Binary.new(Marshal.dump(@template)) + rescue ::Liquid::SyntaxError => error + self.errors.add :template, :liquid_syntax_error + end + end + end + + end + + end + end + end +end \ No newline at end of file diff --git a/app/models/liquid_template.rb b/app/models/liquid_template.rb deleted file mode 100644 index 9f862b01..00000000 --- a/app/models/liquid_template.rb +++ /dev/null @@ -1,32 +0,0 @@ -class LiquidTemplate - - include Locomotive::Mongoid::Document - - ## fields ## - field :name - field :slug - field :value - - ## associations ## - referenced_in :site - - ## callbacks ## - before_validation :normalize_slug - - ## validations ## - validates_presence_of :site, :name, :slug, :value - validates_uniqueness_of :slug, :scope => :site_id - - ## behaviours ## - liquify_template :value - - ## methods ## - - protected - - def normalize_slug - self.slug = self.name.clone if self.slug.blank? && self.name.present? - self.slug.slugify!(:without_extension => true, :downcase => true) if self.slug.present? - end - -end diff --git a/app/models/page.rb b/app/models/page.rb index 72263a90..add97c45 100644 --- a/app/models/page.rb +++ b/app/models/page.rb @@ -5,6 +5,7 @@ class Page ## Extensions ## include Models::Extensions::Page::Tree # include Models::Extensions::Page::Parts + include Models::Extensions::Page::Parse include Models::Extensions::Page::Render include Models::Extensions::Page::Templatized @@ -12,11 +13,10 @@ class Page field :title field :slug field :fullpath + field :raw_template field :published, :type => Boolean, :default => false field :cache_strategy, :default => 'none' - field :layout_template # FIXME: added for liquid inheritance - ## associations ## referenced_in :site @@ -36,10 +36,6 @@ class Page scope :not_found, :where => { :slug => '404', :depth => 0 } scope :published, :where => { :published => true } - ## behaviours ## - # liquify_template :joined_parts - liquify_template :layout_template - ## methods ## def index? diff --git a/app/models/site.rb b/app/models/site.rb index b01f011c..07f491ac 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -83,7 +83,7 @@ class Site self.pages.create({ :slug => slug, :title => I18n.t("attributes.defaults.pages.#{slug}.title"), - :layout_template => I18n.t("attributes.defaults.pages.#{slug}.body"), + :raw_template => I18n.t("attributes.defaults.pages.#{slug}.body"), :published => true }) end diff --git a/app/models/snippet.rb b/app/models/snippet.rb index d7700f04..db547e49 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -1,3 +1,30 @@ -class Snippet < LiquidTemplate +class Snippet + + include Locomotive::Mongoid::Document + + ## fields ## + field :name + field :slug + field :template + + ## associations ## + referenced_in :site + + ## callbacks ## + before_validation :normalize_slug + + ## validations ## + validates_presence_of :site, :name, :slug, :template + validates_uniqueness_of :slug, :scope => :site_id + + ## methods ## + + protected + + def normalize_slug + self.slug = self.name.clone if self.slug.blank? && self.name.present? + self.slug.slugify!(:without_extension => true, :downcase => true) if self.slug.present? + end + end diff --git a/app/views/admin/pages/_form.html.haml b/app/views/admin/pages/_form.html.haml index 657a2b26..a6f22629 100644 --- a/app/views/admin/pages/_form.html.haml +++ b/app/views/admin/pages/_form.html.haml @@ -21,11 +21,11 @@ = f.input :cache_strategy, :as => :select, :collection => options_for_page_cache_strategy, :include_blank => false -= f.foldable_inputs :name => :layout_template do += f.foldable_inputs :name => :raw_template do = f.custom_input :value, :css => 'code full', :with_label => false do - = f.label :layout_template + = f.label :raw_template %code{ :class => 'html' } - = f.text_area :layout_template + = f.text_area :raw_template / .more / = link_to t('admin.image_picker.link'), admin_theme_assets_path, :id => 'image-picker-link' diff --git a/app/views/admin/snippets/_form.html.haml b/app/views/admin/snippets/_form.html.haml index 0d9c87ff..887ff071 100644 --- a/app/views/admin/snippets/_form.html.haml +++ b/app/views/admin/snippets/_form.html.haml @@ -7,8 +7,8 @@ = f.input :slug, :required => false = f.inputs :name => :code do - = f.custom_input :value, :css => 'full', :with_label => false do + = f.custom_input :template, :css => 'full', :with_label => false do %code{ :class => 'html' } - = f.text_area :value + = f.text_area :template .more = link_to t('admin.image_picker.link'), admin_theme_assets_path, :id => 'image-picker-link' \ No newline at end of file diff --git a/config/locales/admin_ui_en.yml b/config/locales/admin_ui_en.yml index e9cd0e8f..85e60488 100644 --- a/config/locales/admin_ui_en.yml +++ b/config/locales/admin_ui_en.yml @@ -245,7 +245,7 @@ en: information: General information meta: SEO Metadata code: Code - layout_template: Layout + raw_template: Layout credentials: Credentials language: Language sites: Sites diff --git a/config/locales/admin_ui_fr.yml b/config/locales/admin_ui_fr.yml index db3e14e1..01efef8e 100644 --- a/config/locales/admin_ui_fr.yml +++ b/config/locales/admin_ui_fr.yml @@ -244,7 +244,7 @@ fr: information: Informations générales meta: SEO Metadata code: Code - layout_template: Gabarit + raw_template: Gabarit credentials: Informations de connexion language: Langue sites: Sites diff --git a/features/engine/inheritance.feature b/features/engine/inheritance.feature index 65807eaf..283a8cb4 100644 --- a/features/engine/inheritance.feature +++ b/features/engine/inheritance.feature @@ -1,4 +1,4 @@ -Feature: Engine +Feature: Inheritance As a designer I want to be able to build more complex page html layouts with shared template code diff --git a/features/engine/snippets.feature b/features/engine/snippets.feature new file mode 100644 index 00000000..d71cf812 --- /dev/null +++ b/features/engine/snippets.feature @@ -0,0 +1,21 @@ +Feature: Snippets + As a designer + I want to insert re-usable piece of code among pages + +Background: + Given I have the site: "test site" set up + And a snippet named "yield" with the template: + """ + HELLO WORLD ! + """ + +Scenario: Simple include + Given a page named "hello-world" with the template: + """ + My application says {% include 'yield' %} + """ + When I view the rendered page at "/hello-world" + Then the rendered output should look like: + """ + My application says HELLO WORLD ! + """ \ No newline at end of file diff --git a/features/step_definitions/admin_steps.rb b/features/step_definitions/admin_steps.rb index 7b748343..759cadbd 100644 --- a/features/step_definitions/admin_steps.rb +++ b/features/step_definitions/admin_steps.rb @@ -27,13 +27,3 @@ end ### Common -# def create_layout_samples -# Factory(:layout, :site => @site, :name => 'One column', :value => %{ -# -# My website -# -# -#
{{ content_for_layout }}
-# -# }) -# end diff --git a/features/step_definitions/page_steps.rb b/features/step_definitions/page_steps.rb index 6b6bdc79..de166a7a 100644 --- a/features/step_definitions/page_steps.rb +++ b/features/step_definitions/page_steps.rb @@ -1,9 +1,9 @@ ### Pages -# helps create a simple content page (parent: "index") with a slug, contents, and layout +# helps create a simple content page (parent: "index") with a slug, contents, and template def create_content_page(page_slug, page_contents, template = nil) @home = @site.pages.where(:slug => "index").first || Factory(:page) - page = @site.pages.create(:slug => page_slug, :body => page_contents, :parent => @home, :title => "some title", :published => true, :layout_template => template) + page = @site.pages.create(:slug => page_slug, :body => page_contents, :parent => @home, :title => "some title", :published => true, :raw_template => template) page.should be_valid page end @@ -46,7 +46,7 @@ Then /^I should have "(.*)" in the (.*) page$/ do |content, page_slug| page = @site.pages.where(:slug => page_slug).first raise "Could not find page: #{page_slug}" unless page - page.layout_template.should == content + page.raw_template.should == content end # checks if the rendered body matches a string diff --git a/features/step_definitions/snippet_steps.rb b/features/step_definitions/snippet_steps.rb new file mode 100644 index 00000000..440ecc96 --- /dev/null +++ b/features/step_definitions/snippet_steps.rb @@ -0,0 +1,16 @@ +### Snippets + +# helps create a simple snippet with a slug and template +def create_snippet(name, template = nil) + snippet = @site.snippets.create(:name => name, :template => template) + snippet.should be_valid + snippet +end + +# creates a snippet + +Given /^a snippet named "([^"]*)" with the template:$/ do |name, template| + @snippet = create_snippet(name, template) +end + + diff --git a/lib/locomotive/liquid.rb b/lib/locomotive/liquid.rb index a07529a9..ad593171 100644 --- a/lib/locomotive/liquid.rb +++ b/lib/locomotive/liquid.rb @@ -1,5 +1,3 @@ %w{. tags drops filters}.each do |dir| Dir[File.join(File.dirname(__FILE__), 'liquid', dir, '*.rb')].each { |lib| require lib } -end - -::Liquid::Template.file_system = Locomotive::Liquid::DbFileSystem.new # enable snippets +end \ No newline at end of file diff --git a/lib/locomotive/liquid/db_file_system.rb b/lib/locomotive/liquid/db_file_system.rb deleted file mode 100644 index fddf4d48..00000000 --- a/lib/locomotive/liquid/db_file_system.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Locomotive - module Liquid - class DbFileSystem - - # Works only with snippets - def read_template_file(site, template_path) - raise FileSystemError, "Illegal snippet name '#{template_path}'" unless template_path =~ /^[^.\/][a-zA-Z0-9_\/]+$/ - - snippet = site.snippets.where(:slug => template_path).first - - raise FileSystemError, "No such snippet '#{template_path}'" if snippet.nil? - - snippet.template - end - - end - end -end diff --git a/lib/locomotive/liquid/liquify_template.rb b/lib/locomotive/liquid/liquify_template.rb deleted file mode 100644 index 3a158005..00000000 --- a/lib/locomotive/liquid/liquify_template.rb +++ /dev/null @@ -1,66 +0,0 @@ -module Locomotive - module Liquid - module LiquifyTemplate - - def self.included(base) - base.extend(ClassMethods) - end - - # Store the parsed version of a liquid template into a column in order to increase performance - # See http://cjohansen.no/en/rails/liquid_email_templates_in_rails - # - # class Page - # liquify_template :body - # end - # - # page = Page.new :body => '...some liquid tags' - # page.template # Liquid::Template - # - # - module ClassMethods - - def liquify_template(source = :value) - field :serialized_template, :type => Binary - before_validation :store_template - - class_eval <<-EOV - def liquify_template_source - self.send(:#{source.to_s}) - end - EOV - - include InstanceMethods - end - - end - - module InstanceMethods - - def template - @template ||= Marshal.load(read_attribute(:serialized_template).to_s) rescue nil - end - - protected - - def store_template - begin - # puts "self.liquify_template_source = #{self.liquify_template_source.inspect}" - @template = ::Liquid::Template.parse(self.liquify_template_source, { :site => self.site }) - @template.root.context.clear - # puts "@template = #{@template.inspect}" - # @template = Locomotive::Liquid::Template.parse(self) - - if self.respond_to?(:after_parse_template) # kind of callback - self.send(:after_parse_template) - end - - self.serialized_template = BSON::Binary.new(Marshal.dump(@template)) - rescue ::Liquid::SyntaxError => error - self.errors.add :template, :liquid_syntax_error - end - end - - end - end - end -end diff --git a/lib/locomotive/liquid/tags/snippet.rb b/lib/locomotive/liquid/tags/snippet.rb index afc85e16..fdda2083 100644 --- a/lib/locomotive/liquid/tags/snippet.rb +++ b/lib/locomotive/liquid/tags/snippet.rb @@ -4,10 +4,21 @@ module Locomotive class Snippet < ::Liquid::Include - def render(context) - site = context.registers[:site] + attr_accessor :partial - partial = ::Liquid::Template.file_system.read_template_file(site, context[@template_name]) + def initialize(tag_name, markup, tokens, context) + super + + snippet = context[:site].snippets.where(:slug => @template_name.gsub('\'', '')).first + + if snippet + @partial = ::Liquid::Template.parse(snippet.template, context) + @partial.root.context.clear + end + end + + def render(context) + return '' if @partial.nil? variable = context[@variable_name || @template_name[1..-2]] @@ -19,11 +30,11 @@ module Locomotive output = (if variable.is_a?(Array) variable.collect do |variable| context[@template_name[1..-2]] = variable - partial.render(context) + @partial.render(context) end else context[@template_name[1..-2]] = variable - partial.render(context) + @partial.render(context) end) output diff --git a/lib/locomotive/mongoid/document.rb b/lib/locomotive/mongoid/document.rb index be877494..4918d989 100644 --- a/lib/locomotive/mongoid/document.rb +++ b/lib/locomotive/mongoid/document.rb @@ -10,7 +10,6 @@ module Locomotive include ::Mongoid::Document include ::Mongoid::Timestamps include ::Mongoid::CustomFields - include Locomotive::Liquid::LiquifyTemplate end end diff --git a/perf/benchmark.rb b/perf/benchmark.rb index f5bf2506..3d8834fd 100755 --- a/perf/benchmark.rb +++ b/perf/benchmark.rb @@ -11,7 +11,7 @@ puts "Starting test..." site = Site.create :name => 'Benchmark Website', :subdomain => 'benchmark' -simple = site.pages.create :title => 'Simple', :slug => 'simple', :layout_template => %{ +simple = site.pages.create :title => 'Simple', :slug => 'simple', :raw_template => %{ @@ -29,7 +29,7 @@ simple = site.pages.create :title => 'Simple', :slug => 'simple', :layout_templa } -base = site.pages.create :title => 'Base page', :slug => 'base', :layout_template => %{ +base = site.pages.create :title => 'Base page', :slug => 'base', :raw_template => %{ @@ -47,13 +47,13 @@ base = site.pages.create :title => 'Base page', :slug => 'base', :layout_templat } -page_1 = site.pages.create :title => 'Page 1', :slug => 'page_1', :layout_template => %{ +page_1 = site.pages.create :title => 'Page 1', :slug => 'page_1', :raw_template => %{ {% extends base %} {% block sidebar %}A sidebar here{% endblock %} {% block body %}
{% block main %}DEFAULT MAIN CONTENT{% endblock %}
{% endblock %} } -page_2 = site.pages.create :title => 'Page 2', :slug => 'page_2', :layout_template => %{ +page_2 = site.pages.create :title => 'Page 2', :slug => 'page_2', :raw_template => %{ {% extends page_1 %} {% block sidebar %}{{ block.super }} / INDEX sidebar{% endblock %} {% block main %}Lorem ipsum{% endblock %} diff --git a/spec/factories.rb b/spec/factories.rb index 93deb56a..17ce2dfc 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -56,59 +56,11 @@ Factory.define :page do |p| end -# Factory.define "unpub" - -## Liquid templates ## -Factory.define :liquid_template do |t| - t.name 'Simple one' - t.slug 'simple_one' - t.value %{simple liquid template} - t.site { Site.where(:subdomain => "acme").first || Factory(:site) } -end - - -# ## Layouts ## -# Factory.define :layout do |l| -# l.name '1 main column + sidebar' -# l.value %{ -# -# My website -# -# -# -#
-# \{% block main %\} -# DEFAULT MAIN CONTENT -# \{% endblock %\} -#
-# -# } -# l.site { Site.where(:subdomain => "acme").first || Factory(:site) } -# end -# -# Factory.define :base_layout, :parent => :layout do |l| -# l.name '1 main column + sidebar' -# l.value %{ -# -# My website -# -# -# -#
\{\{ content_for_layout | textile \}\}
-# -# } -# end - - ## Snippets ## Factory.define :snippet do |s| s.name 'My website title' s.slug 'header' - s.value %{Acme} + s.template %{Acme} s.site { Site.where(:subdomain => "acme").first || Factory(:site) } end diff --git a/spec/lib/locomotive/liquid/tags/snippet_spec.rb b/spec/lib/locomotive/liquid/tags/snippet_spec.rb deleted file mode 100644 index a196165b..00000000 --- a/spec/lib/locomotive/liquid/tags/snippet_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -require 'spec_helper' - -describe Locomotive::Liquid::Tags::Snippet do - - before(:each) do - Site.any_instance.stubs(:create_default_pages!).returns(true) - site = Factory.build(:site) - snippet = Factory.build(:snippet, :site => site) - snippet.send(:store_template) - site.snippets.stubs(:where).returns([snippet]) - @context = ::Liquid::Context.new({}, {}, { :site => site }) - end - - it 'should render it' do - template = ::Liquid::Template.parse("{% include 'header' %}") - text = template.render(@context) - text.should == "Acme" - end - -end diff --git a/spec/models/liquid_template_spec.rb b/spec/models/liquid_template_spec.rb deleted file mode 100644 index 46fbd478..00000000 --- a/spec/models/liquid_template_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -require 'spec_helper' - -describe LiquidTemplate do - - it 'should have a valid factory' do - Factory.build(:liquid_template).should be_valid - end - - # Validations ## - - %w{site name value}.each do |field| - it "should validate presence of #{field}" do - template = Factory.build(:liquid_template, field.to_sym => nil) - template.should_not be_valid - template.errors[field.to_sym].should == ["can't be blank"] - end - end - -end diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb index 7e0a9f23..579a9bcd 100644 --- a/spec/models/snippet_spec.rb +++ b/spec/models/snippet_spec.rb @@ -5,5 +5,15 @@ describe Snippet do it 'should have a valid factory' do Factory.build(:snippet).should be_valid end + + # Validations ## + + %w{site name template}.each do |field| + it "should validate presence of #{field}" do + template = Factory.build(:snippet, field.to_sym => nil) + template.should_not be_valid + template.errors[field.to_sym].should == ["can't be blank"] + end + end end