templatized page can now use models from the main app + add new liquid filters

This commit is contained in:
Didier Lafforgue 2012-02-10 00:57:57 +01:00
parent 39d9c354da
commit 62eaeb10f5
20 changed files with 334 additions and 279 deletions

View File

@ -27,7 +27,7 @@ PATH
carrierwave-mongoid (~> 0.1.3)
cells (~> 3.8.0)
codemirror-rails (~> 2.21)
custom_fields (~> 2.0.0.rc3)
custom_fields (~> 2.0.0.rc4)
devise (~> 1.5.3)
dragonfly (~> 0.9.8)
flash_cookie_session (~> 1.1.1)
@ -56,7 +56,7 @@ PATH
PATH
remote: ../gems/custom_fields
specs:
custom_fields (2.0.0.rc3)
custom_fields (2.0.0.rc4)
activesupport (~> 3.2.1)
carrierwave-mongoid (~> 0.1.3)
mongoid (~> 2.4.3)
@ -123,7 +123,7 @@ GEM
childprocess (0.3.0)
ffi (~> 1.0.6)
chunky_png (1.2.5)
codemirror-rails (2.21)
codemirror-rails (2.21.1)
railties (~> 3.0)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)

View File

@ -21,4 +21,7 @@ class Locomotive.Models.Page extends Backbone.Model
delete hash['editable_elements']
hash.editable_elements = @get('editable_elements').toJSONForSave() if @get('editable_elements')? && @get('editable_elements').length > 0
delete hash['target_klass_name']
hash.target_klass_name = @get('target_klass_name') if @get('templatized') == true
class Locomotive.Models.PagesCollection extends Backbone.Collection

View File

@ -111,9 +111,9 @@ class Locomotive.Views.Pages.FormView extends Locomotive.Views.Shared.FormView
@_enable_checkbox 'templatized',
features: ['slug', 'redirect', 'listed']
on_callback: =>
@$('li#page_content_type_id_input').show()
@$('li#page_target_klass_name_input').show()
off_callback: =>
@$('li#page_content_type_id_input').hide()
@$('li#page_target_klass_name_input').hide()
enable_redirect_checkbox: ->
@_enable_checkbox 'redirect',

View File

@ -15,22 +15,12 @@ module Locomotive
skip_before_filter :verify_authenticity_token
skip_load_and_authorize_resource
self.responder = Locomotive::ActionController::Responder # custom responder
respond_to :json, :xml
rescue_from CanCan::AccessDenied do |exception|
::Locomotive.log "[CanCan::AccessDenied] #{exception.inspect}"
if request.xhr?
render :json => { :error => exception.message }
else
flash[:alert] = exception.message
redirect_to pages_url
end
end
protected
def current_ability

View File

@ -32,6 +32,13 @@ module Locomotive
list
end
def options_for_target_klass_name
base_models = current_site.content_types.map do |type|
[type.name.humanize, type.klass_with_custom_fields(:entries)]
end
base_models + Locomotive.config.models_for_templatization.map { |name| [name.underscore.humanize, name] }
end
def options_for_page_cache_strategy
[
[t('.cache_strategy.none'), 'none'],

View File

@ -57,6 +57,10 @@ module Locomotive
next_or_previous :lt
end
def self.find_by_permalink(permalink)
self.where(:_slug => permalink).first
end
def self.sort_entries!(ids)
list = self.any_in(:_id => ids.map { |id| BSON::ObjectId.from_string(id.to_s) }).to_a
ids.each_with_index do |id, position|

View File

@ -18,103 +18,99 @@ module Locomotive
accepts_nested_attributes_for :editable_elements
end
module InstanceMethods
def disable_parent_editable_elements(block)
self.editable_elements.each { |el| el.disabled = true if el.from_parent? && el.block == block }
end
def disable_parent_editable_elements(block)
self.editable_elements.each { |el| el.disabled = true if el.from_parent? && el.block == block }
def disable_all_editable_elements
self.editable_elements.each { |el| el.disabled = true }
end
def editable_element_blocks
self.editable_elements.collect(&:block)
end
def enabled_editable_elements
self.editable_elements.by_priority.reject { |el| el.disabled? }
end
def editable_elements_grouped_by_blocks
groups = self.enabled_editable_elements.group_by(&:block)
groups.delete_if { |block, elements| elements.empty? }
end
def find_editable_element(block, slug)
self.editable_elements.detect { |el| el.block == block && el.slug == slug }
end
def find_editable_files
self.editable_elements.find_all { |el| el.respond_to?(:source) }
end
def add_or_update_editable_element(attributes, type)
element = self.find_editable_element(attributes[:block], attributes[:slug])
if element
element.attributes = attributes
else
self.editable_elements.build(attributes, type)
end
end
def disable_all_editable_elements
self.editable_elements.each { |el| el.disabled = true }
end
def enable_editable_elements(block)
self.editable_elements.each { |el| el.disabled = false if el.block == block }
end
def editable_element_blocks
self.editable_elements.collect(&:block)
end
def merge_editable_elements_from_page(source)
source.editable_elements.each do |el|
next if el.disabled? or !el.assignable?
def enabled_editable_elements
self.editable_elements.by_priority.reject { |el| el.disabled? }
end
existing_el = self.find_editable_element(el.block, el.slug)
def editable_elements_grouped_by_blocks
groups = self.enabled_editable_elements.group_by(&:block)
groups.delete_if { |block, elements| elements.empty? }
end
if existing_el.nil? # new one from parents
new_attributes = el.attributes.merge(:from_parent => true)
def find_editable_element(block, slug)
self.editable_elements.detect { |el| el.block == block && el.slug == slug }
end
def find_editable_files
self.editable_elements.find_all { |el| el.respond_to?(:source) }
end
def add_or_update_editable_element(attributes, type)
element = self.find_editable_element(attributes[:block], attributes[:slug])
if element
element.attributes = attributes
else
self.editable_elements.build(attributes, type)
end
end
def enable_editable_elements(block)
self.editable_elements.each { |el| el.disabled = false if el.block == block }
end
def merge_editable_elements_from_page(source)
source.editable_elements.each do |el|
next if el.disabled? or !el.assignable?
existing_el = self.find_editable_element(el.block, el.slug)
if existing_el.nil? # new one from parents
new_attributes = el.attributes.merge(:from_parent => true)
if new_attributes['default_attribute'].present?
new_attributes['default_content'] = self.send(new_attributes['default_attribute']) || el.content
else
if el.respond_to?(:content) # only for text
new_attributes['default_content'] = el.content
end
end
self.editable_elements.build(new_attributes, el.class)
elsif existing_el.default_attribute.nil?
existing_el.attributes = { :disabled => false, :default_content => el.content }
if new_attributes['default_attribute'].present?
new_attributes['default_content'] = self.send(new_attributes['default_attribute']) || el.content
else
existing_el.attributes = { :disabled => false }
if el.respond_to?(:content) # only for text
new_attributes['default_content'] = el.content
end
end
self.editable_elements.build(new_attributes, el.class)
elsif existing_el.default_attribute.nil?
existing_el.attributes = { :disabled => false, :default_content => el.content }
else
existing_el.attributes = { :disabled => false }
end
end
end
def remove_disabled_editable_elements
return unless self.editable_elements.any? { |el| el.disabled? }
def remove_disabled_editable_elements
return unless self.editable_elements.any? { |el| el.disabled? }
# super fast way to remove useless elements all in once (TODO callbacks)
self.collection.update(self.atomic_selector, '$pull' => { 'editable_elements' => { 'disabled' => true } })
end
# super fast way to remove useless elements all in once (TODO callbacks)
self.collection.update(self.atomic_selector, '$pull' => { 'editable_elements' => { 'disabled' => true } })
end
protected
protected
## callbacks for editable files
## callbacks for editable files
# equivalent to "after_save :store_source!" in EditableFile
def store_file_sources!
self.find_editable_files.collect(&:store_source!)
end
# equivalent to "after_save :store_source!" in EditableFile
def store_file_sources!
self.find_editable_files.collect(&:store_source!)
end
# equivalent to "before_save :write_source_identifier" in EditableFile
def write_file_source_identifiers
self.find_editable_files.collect(&:write_source_identifier)
end
# equivalent to "after_destroy :remove_source!" in EditableFile
def remove_file_sources!
self.find_editable_files.collect(&:remove_source!)
end
# equivalent to "before_save :write_source_identifier" in EditableFile
def write_file_source_identifiers
self.find_editable_files.collect(&:write_source_identifier)
end
# equivalent to "after_destroy :remove_source!" in EditableFile
def remove_file_sources!
self.find_editable_files.collect(&:remove_source!)
end
end

View File

@ -20,94 +20,90 @@ module Locomotive
scope :pages, lambda { |domain| { :any_in => { :domains => [*domain] } } }
end
module InstanceMethods
def template
@template ||= Marshal.load(self.serialized_template.to_s) rescue nil
end
def template
@template ||= Marshal.load(self.serialized_template.to_s) rescue nil
end
protected
protected
def serialize_template
if self.new_record? || self.raw_template_changed?
@template_changed = true
def serialize_template
if self.new_record? || self.raw_template_changed?
@template_changed = true
@parsing_errors = []
@parsing_errors = []
begin
self._parse_and_serialize_template
rescue ::Liquid::SyntaxError => error
@parsing_errors << I18n.t(:liquid_syntax, :fullpath => self.fullpath, :error => error.to_s, :scope => [:errors, :messages, :page])
rescue ::Locomotive::Liquid::PageNotFound => error
@parsing_errors << I18n.t(:liquid_extend, :fullpath => self.fullpath, :scope => [:errors, :messages, :page])
end
begin
self._parse_and_serialize_template
rescue ::Liquid::SyntaxError => error
@parsing_errors << I18n.t(:liquid_syntax, :fullpath => self.fullpath, :error => error.to_s, :scope => [:errors, :messages, :page])
rescue ::Locomotive::Liquid::PageNotFound => error
@parsing_errors << I18n.t(:liquid_extend, :fullpath => self.fullpath, :scope => [:errors, :messages, :page])
end
end
end
def _parse_and_serialize_template(context = {})
self.parse(context)
self._serialize_template
def _parse_and_serialize_template(context = {})
self.parse(context)
self._serialize_template
end
def _serialize_template
self.serialized_template = BSON::Binary.new(Marshal.dump(@template))
end
def parse(context = {})
self.disable_all_editable_elements
default_context = { :site => self.site, :page => self, :templates => [], :snippets => [] }
context = default_context.merge(context)
@template = ::Liquid::Template.parse(self.raw_template, context)
self.template_dependencies = context[:templates]
self.snippet_dependencies = context[:snippets]
@template.root.context.clear
end
def template_must_be_valid
@parsing_errors.try(:each) do |msg|
self.errors.add :template, msg
self.errors.add :raw_template, msg
end
end
def _serialize_template
self.serialized_template = BSON::Binary.new(Marshal.dump(@template))
end
def update_template_descendants
return unless @template_changed == true
def parse(context = {})
self.disable_all_editable_elements
# we admit at this point that the current template is up-to-date
template_descendants = self.site.pages.any_in(:template_dependencies => [self.id]).to_a
default_context = { :site => self.site, :page => self, :templates => [], :snippets => [] }
# group them by fullpath for better performance
cached = template_descendants.inject({}) { |memo, page| memo[page.fullpath] = page; memo }
context = default_context.merge(context)
self._update_direct_template_descendants(template_descendants.clone, cached)
@template = ::Liquid::Template.parse(self.raw_template, context)
self.template_dependencies = context[:templates]
self.snippet_dependencies = context[:snippets]
@template.root.context.clear
end
def template_must_be_valid
@parsing_errors.try(:each) do |msg|
self.errors.add :template, msg
self.errors.add :raw_template, msg
# finally save them all
::Locomotive::Page.without_callback(:save, :after, :update_template_descendants) do
template_descendants.each do |page|
page.save(:validate => false)
end
end
end
def update_template_descendants
return unless @template_changed == true
# we admit at this point that the current template is up-to-date
template_descendants = self.site.pages.any_in(:template_dependencies => [self.id]).to_a
# group them by fullpath for better performance
cached = template_descendants.inject({}) { |memo, page| memo[page.fullpath] = page; memo }
self._update_direct_template_descendants(template_descendants.clone, cached)
# finally save them all
::Locomotive::Page.without_callback(:save, :after, :update_template_descendants) do
template_descendants.each do |page|
page.save(:validate => false)
end
end
def _update_direct_template_descendants(template_descendants, cached)
direct_descendants = template_descendants.select do |page|
((self.template_dependencies || []) + [self._id]) == (page.template_dependencies || [])
end
def _update_direct_template_descendants(template_descendants, cached)
direct_descendants = template_descendants.select do |page|
((self.template_dependencies || []) + [self._id]) == (page.template_dependencies || [])
end
direct_descendants.each do |page|
page.send(:_parse_and_serialize_template, { :cached_parent => self, :cached_pages => cached })
direct_descendants.each do |page|
page.send(:_parse_and_serialize_template, { :cached_parent => self, :cached_pages => cached })
template_descendants.delete(page) # no need to loop over it next time
template_descendants.delete(page) # no need to loop over it next time
page.send(:_update_direct_template_descendants, template_descendants, cached) # move down
end
page.send(:_update_direct_template_descendants, template_descendants, cached) # move down
end
end
end

View File

@ -7,19 +7,52 @@ module Locomotive
included do
belongs_to :content_type, :class_name => 'Locomotive::ContentType'
field :templatized, :type => Boolean, :default => false
field :target_klass_name
field :content_type_visible_column
## validations ##
validates_presence_of :target_klass_name, :if => :templatized?
validate :ensure_target_klass_name_security
## callbacks ##
before_validation :set_slug_if_templatized
before_validation :ensure_target_klass_name_security
end
module InstanceMethods
def target_klass
target_klass_name.constantize
end
def set_slug_if_templatized
self.slug = 'content_type_template' if self.templatized?
def target_entry_name
if self.target_klass_name =~ /^Locomotive::Entry([a-z0-9]+)$/
@content_type ||= self.site.content_types.find($1)
@content_type.slug.singularize
else
self.target_klass_name.underscore
end
end
def fetch_target_entry(permalink)
target_klass.find_by_permalink(permalink)
end
protected
def set_slug_if_templatized
self.slug = 'content_type_template' if self.templatized?
end
def ensure_target_klass_name_security
return if !self.templatized? || self.target_klass_name.blank?
if self.target_klass_name =~ /^Locomotive::Entry([a-z0-9]+)$/
content_type = Locomotive::ContentType.find($1)
if content_type.site_id != self.site_id
self.errors.add :target_klass_name, :security
end
elsif !Locomotive.config.models_for_templatization.include?(self.target_klass_name)
self.errors.add :target_klass_name, :security
end
end

View File

@ -7,8 +7,12 @@ module Locomotive
self.source.ordered_entries_custom_fields.collect(&:as_json)
end
def klass_name
self.source.klass_with_custom_fields(:entries).to_s
end
def included_methods
super + %w(name description slug order_by order_direction highlighted_field_name group_by_field_name api_accounts entries_custom_fields)
super + %w(name description slug order_by order_direction highlighted_field_name group_by_field_name api_accounts entries_custom_fields klass_name)
end
end

View File

@ -30,10 +30,10 @@
= f.inputs :name => :advanced_options, :id => 'advanced-options', :class => "inputs foldable #{'folded' if inputs_folded?(@page)}" do
= f.input :content_type_id, :as => :select, :collection => current_site.content_types.all.to_a, :include_blank => false, :wrapper_html => { :style => "#{'display: none' unless @page.templatized?}" }
= f.input :templatized, :as => :'Locomotive::Toggle', :style => "#{'display: none' if @page.redirect?}"
= f.input :target_klass_name, :as => :select, :collection => options_for_target_klass_name, :include_blank => false, :wrapper_html => { :style => "#{'display: none' unless @page.templatized?}" }
= f.input :published, :as => :'Locomotive::Toggle'
= f.input :listed, :as => :'Locomotive::Toggle'

View File

@ -33,7 +33,7 @@ fr:
extname_changed: "Nouveau fichier n'a pas l'extension original"
array_too_short: "est trop petit (le nombre minimum d'éléments est %{count})"
liquid_syntax: "Erreur de syntaxe ('%{error}')"
invalid_theme_file: "doit être rempli ou n'est pas un fichier zip"
security: "présente un problème de sécurité"
page:
liquid_syntax: "Erreur de syntaxe dans les sections de page, veuillez vérifier la syntaxe ('%{error}'/'%{fullpath}')"
liquid_extend: "La page '%{fullpath}' étend le contenu d'une page qui n'existe pas"

View File

@ -54,6 +54,7 @@ en:
password_confirmation: New password confirmation
page:
seo_title: Title
target_klass_name: Model
site:
locales: Languages
@ -63,7 +64,7 @@ en:
cache_strategy: "Cache the page for better performance. The 'Simple' choice is a good compromise."
templatized: "Use the page as a template for a model you defined."
listed: "Control whether to show the page from generated menus."
content_type_id: "The type of content this page will be a template for."
target_klass_name: "The type of content this page will be a template for."
seo_title: "Define a page title which should be used as the value for the title tag in the head section. Leave it empty if you want to use the default value from the site settings."
meta_keywords: "Overrides the site's meta keywords used within the head tag of the page. They are separated by a comma."
meta_description: "Overrides the site's meta description used within the head tag of the page."

View File

@ -51,7 +51,7 @@ Locomotive.configure do |config|
# tell if logs are enabled. Useful for debug purpose.
config.enable_logs = true
# Configure the e-mail address which will be shown in the DeviseMailer, NotificationMailer, ...etc
# configure the e-mail address which will be shown in the DeviseMailer, NotificationMailer, ...etc
# if you do not put the domain name in the email, Locomotive will take the default domain name depending
# on your deployment target (server, Heroku, Bushido, ...etc)
#
@ -65,6 +65,9 @@ Locomotive.configure do |config|
# follow the Dependency Injection pattern
# config.context_assign_extensions = {}
# add extra classes other than the defined content types among a site which will potentially used by the templatized pages.
# config.models_for_templatization = %w(Product)
# Rack-cache settings, mainly used for the inline resizing image module. Default options:
# config.rack_cache = {
# :verbose => true,

View File

@ -43,7 +43,6 @@ module Locomotive
end
def localized?
Rails.logger.debug "localized? #{@locomotive_localized.inspect}"
!!@locomotive_localized
end

View File

@ -27,7 +27,8 @@ module Locomotive
:entitystore => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/body")
},
:devise_modules => [:rememberable, :database_authenticatable, :token_authenticatable, :recoverable, :trackable, :validatable, :encryptable, { :encryptor => :sha1 }],
:context_assign_extensions => { }
:context_assign_extensions => { },
:models_for_templatization => []
}
cattr_accessor :settings

View File

@ -11,6 +11,10 @@ module Locomotive
input.to_s.gsub(' ', '-').gsub('/', '-').dasherize
end
def multi_line(input)
input.to_s.gsub("\n", '<br/>')
end
def concat(input, *args)
result = input.to_s
args.flatten.each { |a| result << a.to_s }
@ -21,6 +25,14 @@ module Locomotive
(index.to_i + 1) % modulo == 0 ? word : ''
end
def first(input)
input.first
end
def last(input)
input.last
end
end
::Liquid::Template.register_filter(Misc)

View File

@ -3,126 +3,122 @@ module Locomotive
extend ActiveSupport::Concern
module InstanceMethods
protected
protected
def render_locomotive_page
if request.fullpath =~ /^\/admin\//
render :template => '/locomotive/errors/404', :layout => '/admin/layouts/not_logged_in', :status => :not_found
else
@page = locomotive_page
def render_locomotive_page
if request.fullpath =~ /^\/admin\//
render :template => '/locomotive/errors/404', :layout => '/admin/layouts/not_logged_in', :status => :not_found
redirect_to(@page.redirect_url) and return if @page.present? && @page.redirect?
render_no_page_error and return if @page.nil?
output = @page.render(locomotive_context)
self.prepare_and_set_response(output)
end
end
def render_no_page_error
render :template => '/locomotive/errors/no_page', :layout => false
end
def locomotive_page
path = (params[:path] || params[:page_path] || request.fullpath).clone # TODO: params[:path] is more consistent
path = path.split('?').first # take everything before the query string or the lookup fails
path.gsub!(/\.[a-zA-Z][a-zA-Z0-9]{2,}$/, '') # remove the page extension
path.gsub!(/^\//, '') # remove the leading slash
path = 'index' if path.blank? || path == '_edit'
if path != 'index'
dirname = File.dirname(path).gsub(/^\.$/, '') # also look for templatized page path
path = [path, File.join(dirname, 'content_type_template').gsub(/^\//, '')]
end
if page = current_site.pages.any_in(:fullpath => [*path]).first
if not page.published? and current_locomotive_account.nil?
page = nil
else
@page = locomotive_page
if page.templatized?
@content_entry = page.fetch_target_entry(File.basename(path.first))
redirect_to(@page.redirect_url) and return if @page.present? && @page.redirect?
render_no_page_error and return if @page.nil?
output = @page.render(locomotive_context)
self.prepare_and_set_response(output)
end
end
def render_no_page_error
render :template => '/locomotive/errors/no_page', :layout => false
end
def locomotive_page
path = (params[:path] || params[:page_path] || request.fullpath).clone # TODO: params[:path] is more consistent
path = path.split('?').first # take everything before the query string or the lookup fails
path.gsub!(/\.[a-zA-Z][a-zA-Z0-9]{2,}$/, '') # remove the page extension
path.gsub!(/^\//, '') # remove the leading slash
path = 'index' if path.blank? || path == '_edit'
if path != 'index'
dirname = File.dirname(path).gsub(/^\.$/, '') # also look for templatized page path
path = [path, File.join(dirname, 'content_type_template').gsub(/^\//, '')]
end
if page = current_site.pages.any_in(:fullpath => [*path]).first
if not page.published? and current_locomotive_account.nil?
page = nil
else
if page.templatized?
@content_entry = page.content_type.entries.where(:_slug => File.basename(path.first)).first
if @content_entry.nil? || (!@content_entry.visible? && current_locomotive_account.nil?) # content instance not found or not visible
page = nil
end
if @content_entry.nil? || (!@content_entry.visible? && current_locomotive_account.nil?) # content instance not found or not visible
page = nil
end
end
end
page || not_found_page
end
def locomotive_context
assigns = {
'site' => current_site,
'page' => @page,
'models' => Locomotive::Liquid::Drops::ContentTypes.new,
'contents' => Locomotive::Liquid::Drops::ContentTypes.new, # DEPRECATED
'current_page' => self.params[:page],
'params' => self.params,
'path' => request.path,
'url' => request.url,
'now' => Time.now.utc,
'today' => Date.today,
'locale' => I18n.locale,
'default_locale' => current_site.default_locale.to_s,
'locales' => current_site.locales
}
page || not_found_page
end
assigns.merge!(Locomotive.config.context_assign_extensions)
def locomotive_context
assigns = {
'site' => current_site,
'page' => @page,
'models' => Locomotive::Liquid::Drops::ContentTypes.new,
'contents' => Locomotive::Liquid::Drops::ContentTypes.new, # DEPRECATED
'current_page' => self.params[:page],
'params' => self.params,
'path' => request.path,
'url' => request.url,
'now' => Time.now.utc,
'today' => Date.today,
'locale' => I18n.locale,
'default_locale' => current_site.default_locale.to_s,
'locales' => current_site.locales
}
assigns.merge!(flash.to_hash.stringify_keys) # data from public submissions
assigns.merge!(Locomotive.config.context_assign_extensions)
if @page.templatized? # add instance from content type
assigns['entry'] = @content_entry
assigns[@page.content_type.slug.singularize] = @content_entry # just here to help to write readable liquid code
assigns.merge!(flash.to_hash.stringify_keys) # data from public submissions
if @page.templatized? # add instance from content type
assigns['entry'] = @content_entry
assigns[@page.target_entry_name] = @content_entry # just here to help to write readable liquid code
end
registers = {
:controller => self,
:site => current_site,
:page => @page,
:inline_editor => self.editing_page?,
:current_locomotive_account => current_locomotive_account
}
::Liquid::Context.new({}, assigns, registers, false) # switch from false to true to enable the re-thrown exception flag
end
def prepare_and_set_response(output)
flash.discard
response.headers['Content-Type'] = 'text/html; charset=utf-8'
response.headers['Editable'] = 'true' unless self.editing_page?
if @page.with_cache?
fresh_when :etag => @page, :last_modified => @page.updated_at.utc, :public => true
if @page.cache_strategy != 'simple' # varnish
response.cache_control[:max_age] = @page.cache_strategy
end
registers = {
:controller => self,
:site => current_site,
:page => @page,
:inline_editor => self.editing_page?,
:current_locomotive_account => current_locomotive_account
}
::Liquid::Context.new({}, assigns, registers, false) # switch from false to true to enable the re-thrown exception flag
end
def prepare_and_set_response(output)
flash.discard
render :text => output, :layout => false, :status => page_status unless performed?
end
response.headers['Content-Type'] = 'text/html; charset=utf-8'
response.headers['Editable'] = 'true' unless self.editing_page?
def not_found_page
current_site.pages.not_found.published.first
end
if @page.with_cache?
fresh_when :etag => @page, :last_modified => @page.updated_at.utc, :public => true
if @page.cache_strategy != 'simple' # varnish
response.cache_control[:max_age] = @page.cache_strategy
end
end
render :text => output, :layout => false, :status => page_status unless performed?
end
def not_found_page
current_site.pages.not_found.published.first
end
def editing_page?
!!@editing
end
def page_status
@page.not_found? ? :not_found : :ok
end
def editing_page?
!!@editing
end
def page_status
@page.not_found? ? :not_found : :ok
end
end

View File

@ -0,0 +1,7 @@
class Foo
include Mongoid::Document
field :name
end

View File

@ -66,6 +66,9 @@ Locomotive.configure do |config|
# follow the Dependency Injection pattern
# config.context_assign_extensions = {}
# add extra classes other than the defined content types among a site which will potentially used by the templatized pages.
config.models_for_templatization = %w(Foo)
# Rack-cache settings, mainly used for the inline resizing image module. Default options:
# config.rack_cache = {
# :verbose => true,