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,8 +18,6 @@ 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
@ -116,8 +114,6 @@ module Locomotive
end
end
end
end
end
end

View File

@ -20,8 +20,6 @@ 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
@ -109,8 +107,6 @@ module Locomotive
end
end
end
end
end
end

View File

@ -7,21 +7,54 @@ 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 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
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,8 +3,6 @@ module Locomotive
extend ActiveSupport::Concern
module InstanceMethods
protected
def render_locomotive_page
@ -45,7 +43,7 @@ module Locomotive
page = nil
else
if page.templatized?
@content_entry = page.content_type.entries.where(:_slug => File.basename(path.first)).first
@content_entry = page.fetch_target_entry(File.basename(path.first))
if @content_entry.nil? || (!@content_entry.visible? && current_locomotive_account.nil?) # content instance not found or not visible
page = nil
@ -80,7 +78,7 @@ module Locomotive
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[@page.target_entry_name] = @content_entry # just here to help to write readable liquid code
end
registers = {
@ -124,6 +122,4 @@ module Locomotive
end
end
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,