custom fields has its own repo + upgrade code for Mongoid beta 16 + clean code + fix rspec tests
This commit is contained in:
parent
53500bda9e
commit
e25ded881b
3
Gemfile
3
Gemfile
@ -6,7 +6,7 @@ gem 'rails', '3.0.0.rc'
|
|||||||
gem 'liquid', :git => 'git://github.com/locomotivecms/liquid.git', :ref => 'a41213c77cbc81dab87d'
|
gem 'liquid', :git => 'git://github.com/locomotivecms/liquid.git', :ref => 'a41213c77cbc81dab87d'
|
||||||
|
|
||||||
gem 'bson_ext', '>= 1.0.1'
|
gem 'bson_ext', '>= 1.0.1'
|
||||||
gem 'mongoid', :git => 'git://github.com/durran/mongoid.git', :ref => 'e387a0d1dc74da057472'
|
gem 'mongoid', '2.0.0.beta.16'
|
||||||
gem 'mongoid_acts_as_tree', '0.1.5'
|
gem 'mongoid_acts_as_tree', '0.1.5'
|
||||||
gem 'mongo_session_store', '2.0.0.pre'
|
gem 'mongo_session_store', '2.0.0.pre'
|
||||||
gem 'warden'
|
gem 'warden'
|
||||||
@ -22,6 +22,7 @@ gem 'heroku'
|
|||||||
gem 'httparty', '0.6.1'
|
gem 'httparty', '0.6.1'
|
||||||
gem 'RedCloth'
|
gem 'RedCloth'
|
||||||
gem 'inherited_resources', '1.1.2'
|
gem 'inherited_resources', '1.1.2'
|
||||||
|
gem 'custom_fields', :git => 'git://github.com/locomotivecms/custom_fields.git'
|
||||||
gem 'jeweler'
|
gem 'jeweler'
|
||||||
|
|
||||||
# Development environment
|
# Development environment
|
||||||
|
29
Gemfile.lock
29
Gemfile.lock
@ -1,15 +1,3 @@
|
|||||||
GIT
|
|
||||||
remote: git://github.com/durran/mongoid.git
|
|
||||||
revision: e387a0d
|
|
||||||
ref: e387a0d1dc74da057472
|
|
||||||
specs:
|
|
||||||
mongoid (2.0.0.beta.15)
|
|
||||||
activemodel (= 3.0.0.rc)
|
|
||||||
bson (= 1.0.4)
|
|
||||||
mongo (= 1.0.6)
|
|
||||||
tzinfo (= 0.3.22)
|
|
||||||
will_paginate (~> 3.0.pre)
|
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
remote: git://github.com/floehopper/mocha.git
|
remote: git://github.com/floehopper/mocha.git
|
||||||
revision: d1715ff
|
revision: d1715ff
|
||||||
@ -17,6 +5,12 @@ GIT
|
|||||||
mocha (0.9.8.20090918115329)
|
mocha (0.9.8.20090918115329)
|
||||||
rake
|
rake
|
||||||
|
|
||||||
|
GIT
|
||||||
|
remote: git://github.com/locomotivecms/custom_fields.git
|
||||||
|
revision: d393307
|
||||||
|
specs:
|
||||||
|
custom_fields (0.0.0.1)
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
remote: git://github.com/locomotivecms/liquid.git
|
remote: git://github.com/locomotivecms/liquid.git
|
||||||
revision: a41213c
|
revision: a41213c
|
||||||
@ -152,10 +146,16 @@ GEM
|
|||||||
treetop (>= 1.4.5)
|
treetop (>= 1.4.5)
|
||||||
mime-types (1.16)
|
mime-types (1.16)
|
||||||
mimetype-fu (0.1.2)
|
mimetype-fu (0.1.2)
|
||||||
mongo (1.0.6)
|
mongo (1.0.7)
|
||||||
bson (>= 1.0.4)
|
bson (>= 1.0.4)
|
||||||
mongo_session_store (2.0.0.pre)
|
mongo_session_store (2.0.0.pre)
|
||||||
actionpack (~> 3.0)
|
actionpack (~> 3.0)
|
||||||
|
mongoid (2.0.0.beta.16)
|
||||||
|
activemodel (= 3.0.0.rc)
|
||||||
|
bson (= 1.0.4)
|
||||||
|
mongo (= 1.0.7)
|
||||||
|
tzinfo (= 0.3.22)
|
||||||
|
will_paginate (~> 3.0.pre)
|
||||||
mongoid_acts_as_tree (0.1.5)
|
mongoid_acts_as_tree (0.1.5)
|
||||||
bson (>= 0.20.1)
|
bson (>= 0.20.1)
|
||||||
mongoid (<= 2.0.0)
|
mongoid (<= 2.0.0)
|
||||||
@ -246,6 +246,7 @@ DEPENDENCIES
|
|||||||
cgi_multipart_eof_fix
|
cgi_multipart_eof_fix
|
||||||
cucumber
|
cucumber
|
||||||
cucumber-rails
|
cucumber-rails
|
||||||
|
custom_fields!
|
||||||
database_cleaner
|
database_cleaner
|
||||||
devise!
|
devise!
|
||||||
factory_girl_rails
|
factory_girl_rails
|
||||||
@ -262,7 +263,7 @@ DEPENDENCIES
|
|||||||
mimetype-fu
|
mimetype-fu
|
||||||
mocha!
|
mocha!
|
||||||
mongo_session_store (= 2.0.0.pre)
|
mongo_session_store (= 2.0.0.pre)
|
||||||
mongoid!
|
mongoid (= 2.0.0.beta.16)
|
||||||
mongoid_acts_as_tree (= 0.1.5)
|
mongoid_acts_as_tree (= 0.1.5)
|
||||||
mongrel
|
mongrel
|
||||||
pickle!
|
pickle!
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
module Admin
|
|
||||||
class LayoutsController < BaseController
|
|
||||||
|
|
||||||
sections 'settings'
|
|
||||||
|
|
||||||
respond_to :json, :only => :update
|
|
||||||
|
|
||||||
def index
|
|
||||||
@layouts = current_site.layouts.order_by([[:name, :asc]])
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,15 +1,16 @@
|
|||||||
module Admin
|
# @DEPRECATED
|
||||||
class PagePartsController < BaseController
|
# module Admin
|
||||||
|
# class PagePartsController < BaseController
|
||||||
layout nil
|
#
|
||||||
|
# layout nil
|
||||||
respond_to :json
|
#
|
||||||
|
# respond_to :json
|
||||||
def index
|
#
|
||||||
parts = current_site.layouts.find(params[:layout_id]).parts
|
# def index
|
||||||
|
# parts = current_site.layouts.find(params[:layout_id]).parts
|
||||||
respond_with parts.collect(&:attributes)
|
#
|
||||||
end
|
# respond_with parts.collect(&:attributes)
|
||||||
|
# end
|
||||||
end
|
#
|
||||||
end
|
# end
|
||||||
|
# end
|
||||||
|
@ -1,58 +1,59 @@
|
|||||||
module Models
|
# @DEPRECATED
|
||||||
module Extensions
|
# module Models
|
||||||
module Page
|
# module Extensions
|
||||||
module Parts
|
# module Page
|
||||||
|
# module Parts
|
||||||
extend ActiveSupport::Concern
|
#
|
||||||
|
# extend ActiveSupport::Concern
|
||||||
included do
|
#
|
||||||
embeds_many :parts, :class_name => 'PagePart'
|
# included do
|
||||||
|
# embeds_many :parts, :class_name => 'PagePart'
|
||||||
before_validation do |p|
|
#
|
||||||
if p.parts.empty?
|
# before_validation do |p|
|
||||||
p.parts << PagePart.build_body_part(p.respond_to?(:body) ? p.body : nil)
|
# if p.parts.empty?
|
||||||
end
|
# p.parts << PagePart.build_body_part(p.respond_to?(:body) ? p.body : nil)
|
||||||
end
|
# end
|
||||||
end
|
# end
|
||||||
|
# end
|
||||||
module InstanceMethods
|
#
|
||||||
|
# module InstanceMethods
|
||||||
def parts_attributes=(attributes)
|
#
|
||||||
self.update_parts(attributes.values.map { |attrs| PagePart.new(attrs) })
|
# def parts_attributes=(attributes)
|
||||||
end
|
# self.update_parts(attributes.values.map { |attrs| PagePart.new(attrs) })
|
||||||
|
# end
|
||||||
def joined_parts
|
#
|
||||||
self.parts.enabled.map(&:template).join('')
|
# def joined_parts
|
||||||
end
|
# self.parts.enabled.map(&:template).join('')
|
||||||
|
# end
|
||||||
protected
|
#
|
||||||
|
# protected
|
||||||
def update_parts(parts)
|
#
|
||||||
performed = []
|
# def update_parts(parts)
|
||||||
|
# performed = []
|
||||||
# add / update
|
#
|
||||||
parts.each do |part|
|
# # add / update
|
||||||
if (existing = self.parts.detect { |p| p.id == part.id || p.slug == part.slug })
|
# parts.each do |part|
|
||||||
existing.attributes = part.attributes.delete_if { |k, v| %w{_id slug}.include?(k) }
|
# if (existing = self.parts.detect { |p| p.id == part.id || p.slug == part.slug })
|
||||||
else
|
# existing.attributes = part.attributes.delete_if { |k, v| %w{_id slug}.include?(k) }
|
||||||
self.parts << (existing = part)
|
# else
|
||||||
end
|
# self.parts << (existing = part)
|
||||||
performed << existing unless existing.disabled?
|
# end
|
||||||
end
|
# performed << existing unless existing.disabled?
|
||||||
|
# end
|
||||||
# disable missing parts
|
#
|
||||||
(self.parts.map(&:slug) - performed.map(&:slug)).each do |slug|
|
# # disable missing parts
|
||||||
self.parts.detect { |p| p.slug == slug }.disabled = true
|
# (self.parts.map(&:slug) - performed.map(&:slug)).each do |slug|
|
||||||
end
|
# self.parts.detect { |p| p.slug == slug }.disabled = true
|
||||||
end
|
# end
|
||||||
|
# end
|
||||||
def update_parts!(new_parts)
|
#
|
||||||
self.update_parts(new_parts)
|
# def update_parts!(new_parts)
|
||||||
self.save
|
# self.update_parts(new_parts)
|
||||||
end
|
# self.save
|
||||||
|
# end
|
||||||
end
|
#
|
||||||
end
|
# end
|
||||||
end
|
# end
|
||||||
end
|
# end
|
||||||
end
|
# end
|
||||||
|
# end
|
||||||
|
@ -5,15 +5,6 @@ module Models
|
|||||||
|
|
||||||
def render(context)
|
def render(context)
|
||||||
self.template.render(context)
|
self.template.render(context)
|
||||||
|
|
||||||
# FIXME : old code based on layout / parts
|
|
||||||
# self.template.render(context)
|
|
||||||
#
|
|
||||||
# if self.layout
|
|
||||||
# self.layout.template.render(context)
|
|
||||||
# else
|
|
||||||
# ::Liquid::Template.parse("{{ content_for_layout }}").render(context)
|
|
||||||
# end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -24,6 +24,7 @@ module Models
|
|||||||
|
|
||||||
# Fixme (Didier L.): Instances methods are defined before the include itself
|
# Fixme (Didier L.): Instances methods are defined before the include itself
|
||||||
alias :fix_position :hacked_fix_position
|
alias :fix_position :hacked_fix_position
|
||||||
|
alias :descendants :hacked_descendants
|
||||||
end
|
end
|
||||||
|
|
||||||
module InstanceMethods
|
module InstanceMethods
|
||||||
@ -42,6 +43,11 @@ module Models
|
|||||||
self.instance_variable_set :@_will_move, true
|
self.instance_variable_set :@_will_move, true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def hacked_descendants
|
||||||
|
return [] if new_record?
|
||||||
|
self.class.all_in(path_field => [self._id]).order_by tree_order
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def change_parent
|
def change_parent
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
# @deprecated
|
|
||||||
class Layout < LiquidTemplate
|
|
||||||
|
|
||||||
# acts_as_tree
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
# TODO: move that in the liquify_template module
|
|
||||||
|
|
||||||
def after_parse_template
|
|
||||||
blocks = self.find_blocks(self.template.root)
|
|
||||||
self.template.send(:instance_variable_set, :"@parent_blocks", blocks)
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_blocks(node, blocks = {})
|
|
||||||
if node.respond_to?(:nodelist) && node.nodelist
|
|
||||||
node.nodelist.inject(blocks) do |b, node|
|
|
||||||
if node.is_a?(Locomotive::Liquid::Tags::Block)
|
|
||||||
b[node.name] = node
|
|
||||||
end
|
|
||||||
self.find_blocks(node, b) # FIXME: find nested blocks too
|
|
||||||
b
|
|
||||||
end
|
|
||||||
end
|
|
||||||
blocks
|
|
||||||
end
|
|
||||||
|
|
||||||
## associations ##
|
|
||||||
|
|
||||||
# references_many :pages
|
|
||||||
# embeds_many :parts, :class_name => 'PagePart'
|
|
||||||
|
|
||||||
## callbacks ##
|
|
||||||
# before_save :build_parts_from_value
|
|
||||||
# after_save :update_parts_in_pages
|
|
||||||
|
|
||||||
## validations ##
|
|
||||||
# validates_format_of :value, :with => Locomotive::Regexps::CONTENT_FOR_LAYOUT, :message => :missing_content_for_layout
|
|
||||||
|
|
||||||
## methods ##
|
|
||||||
|
|
||||||
# protected
|
|
||||||
#
|
|
||||||
# def build_parts_from_value
|
|
||||||
# if self.value_changed? || self.new_record?
|
|
||||||
# self.parts.each { |p| p.disabled = true }
|
|
||||||
#
|
|
||||||
# self.value.scan(Locomotive::Regexps::CONTENT_FOR).each do |attributes|
|
|
||||||
# slug = attributes[0].strip.downcase
|
|
||||||
# name = slug.humanize
|
|
||||||
# name = I18n.t('attributes.defaults.page_parts.name') if slug == 'layout'
|
|
||||||
#
|
|
||||||
# if part = self.parts.detect { |p| p.slug == slug }
|
|
||||||
# part.name = name if name.present?
|
|
||||||
# part.disabled = false
|
|
||||||
# else
|
|
||||||
# self.parts.build :slug => slug, :name => name || slug
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# # body always first
|
|
||||||
# body = self.parts.detect { |p| p.slug == 'layout' }
|
|
||||||
# self.parts.delete(body)
|
|
||||||
# self.parts.insert(0, body)
|
|
||||||
#
|
|
||||||
# @_update_pages = true if self.value_changed?
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# def update_parts_in_pages
|
|
||||||
# self.pages.each { |p| p.send(:update_parts!, self.parts) } if @_update_pages
|
|
||||||
# end
|
|
||||||
|
|
||||||
end
|
|
@ -22,7 +22,6 @@ class Page
|
|||||||
|
|
||||||
## associations ##
|
## associations ##
|
||||||
referenced_in :site
|
referenced_in :site
|
||||||
# referenced_in :layout
|
|
||||||
|
|
||||||
## callbacks ##
|
## callbacks ##
|
||||||
before_validation :normalize_slug
|
before_validation :normalize_slug
|
||||||
|
@ -1,35 +1,36 @@
|
|||||||
class PagePart
|
# @DEPRECATED
|
||||||
|
# class PagePart
|
||||||
include Mongoid::Document
|
#
|
||||||
|
# include Mongoid::Document
|
||||||
## fields ##
|
#
|
||||||
field :name
|
# ## fields ##
|
||||||
field :slug
|
# field :name
|
||||||
field :value
|
# field :slug
|
||||||
field :disabled, :type => Boolean, :default => false
|
# field :value
|
||||||
field :value
|
# field :disabled, :type => Boolean, :default => false
|
||||||
|
# field :value
|
||||||
## associations ##
|
#
|
||||||
embedded_in :page, :inverse_of => :parts
|
# ## associations ##
|
||||||
|
# embedded_in :page, :inverse_of => :parts
|
||||||
## validations ##
|
#
|
||||||
validates_presence_of :name, :slug
|
# ## validations ##
|
||||||
|
# validates_presence_of :name, :slug
|
||||||
## named scopes ##
|
#
|
||||||
scope :enabled, where(:disabled => false)
|
# ## named scopes ##
|
||||||
|
# scope :enabled, where(:disabled => false)
|
||||||
## methods ##
|
#
|
||||||
|
# ## methods ##
|
||||||
def template
|
#
|
||||||
"{% capture content_for_#{self.slug} %}#{self.value}{% endcapture %}"
|
# def template
|
||||||
end
|
# "{% capture content_for_#{self.slug} %}#{self.value}{% endcapture %}"
|
||||||
|
# end
|
||||||
def self.build_body_part(body_content = nil)
|
#
|
||||||
self.new({
|
# def self.build_body_part(body_content = nil)
|
||||||
:name => I18n.t('attributes.defaults.page_parts.name'),
|
# self.new({
|
||||||
:value => body_content || I18n.t('attributes.defaults.pages.other.body'),
|
# :name => I18n.t('attributes.defaults.page_parts.name'),
|
||||||
:slug => 'layout'
|
# :value => body_content || I18n.t('attributes.defaults.pages.other.body'),
|
||||||
})
|
# :slug => 'layout'
|
||||||
end
|
# })
|
||||||
|
# end
|
||||||
end
|
#
|
||||||
|
# end
|
||||||
|
@ -11,11 +11,10 @@ class Site
|
|||||||
|
|
||||||
## associations ##
|
## associations ##
|
||||||
references_many :pages
|
references_many :pages
|
||||||
references_many :layouts
|
references_many :snippets, :dependent => :destroy
|
||||||
references_many :snippets
|
references_many :theme_assets, :dependent => :destroy
|
||||||
references_many :theme_assets
|
references_many :asset_collections, :dependent => :destroy
|
||||||
references_many :asset_collections
|
references_many :content_types, :dependent => :destroy
|
||||||
references_many :content_types
|
|
||||||
embeds_many :memberships
|
embeds_many :memberships
|
||||||
|
|
||||||
## validations ##
|
## validations ##
|
||||||
@ -28,11 +27,13 @@ class Site
|
|||||||
## callbacks ##
|
## callbacks ##
|
||||||
after_create :create_default_pages!
|
after_create :create_default_pages!
|
||||||
before_save :add_subdomain_to_domains
|
before_save :add_subdomain_to_domains
|
||||||
after_destroy :destroy_in_cascade!
|
after_destroy :destroy_pages
|
||||||
|
|
||||||
## named scopes ##
|
## named scopes ##
|
||||||
scope :match_domain, lambda { |domain| { :where => { :domains => domain } } }
|
scope :match_domain, lambda { |domain| { :any_in => { :domains => [*domain] } } }
|
||||||
scope :match_domain_with_exclusion_of, lambda { |domain, site| { :where => { :domains => domain, :_id.ne => site.id } } }
|
scope :match_domain_with_exclusion_of, lambda { |domain, site|
|
||||||
|
{ :any_in => { :domains => [*domain] }, :where => { :_id.ne => site.id } }
|
||||||
|
}
|
||||||
|
|
||||||
## methods ##
|
## methods ##
|
||||||
|
|
||||||
@ -67,7 +68,7 @@ class Site
|
|||||||
return if self.domains.empty?
|
return if self.domains.empty?
|
||||||
|
|
||||||
self.domains_without_subdomain.each do |domain|
|
self.domains_without_subdomain.each do |domain|
|
||||||
if not self.class.match_domain_with_exclusion_of(domain, self).empty?
|
if self.class.match_domain_with_exclusion_of(domain, self).any?
|
||||||
self.errors.add(:domains, :domain_taken, :value => domain)
|
self.errors.add(:domains, :domain_taken, :value => domain)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -88,10 +89,9 @@ class Site
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy_in_cascade!
|
def destroy_pages
|
||||||
%w{pages layouts snippets theme_assets asset_collections content_types}.each do |association|
|
# pages is a tree so we just need to delete the root (as well as the page not found page)
|
||||||
self.send(association).destroy_all
|
self.pages.index.first.try(:destroy) && self.pages.not_found.first.try(:destroy)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
- content_for :head do
|
|
||||||
= javascript_include_tag 'admin/plugins/codemirror/codemirror', 'admin/layouts.js'
|
|
||||||
= image_picker_include_tags
|
|
||||||
|
|
||||||
= f.inputs :name => :information do
|
|
||||||
= f.input :name
|
|
||||||
|
|
||||||
= f.inputs :name => :code do
|
|
||||||
= f.custom_input :value, :css => 'code full', :with_label => false do
|
|
||||||
%code{ :class => 'html' }
|
|
||||||
= f.text_area :value
|
|
||||||
.more
|
|
||||||
= link_to t('admin.image_picker.link'), admin_theme_assets_path, :id => 'image-picker-link'
|
|
@ -1,7 +0,0 @@
|
|||||||
%li
|
|
||||||
%strong= link_to layout.name, edit_admin_layout_path(layout)
|
|
||||||
.more
|
|
||||||
%span!= t('.updated_at')
|
|
||||||
= l layout.updated_at, :format => :short
|
|
||||||
|
|
||||||
= link_to image_tag('admin/list/icons/trash.png'), admin_layout_path(layout), :class => 'remove', :confirm => t('admin.messages.confirm'), :method => :delete
|
|
@ -1,15 +0,0 @@
|
|||||||
- title t('.title')
|
|
||||||
|
|
||||||
- content_for :submenu do
|
|
||||||
= render 'admin/shared/menu/settings'
|
|
||||||
|
|
||||||
- content_for :buttons do
|
|
||||||
= admin_button_tag :new, new_admin_layout_url, :class => 'new'
|
|
||||||
|
|
||||||
%p!= t('.help')
|
|
||||||
|
|
||||||
= semantic_form_for @layout, :url => admin_layout_url(@layout), :html => { :class => 'save-with-shortcut' } do |form|
|
|
||||||
|
|
||||||
= render 'form', :f => form
|
|
||||||
|
|
||||||
= render 'admin/shared/form_actions', :back_url => admin_layouts_url, :button_label => :update
|
|
@ -1,15 +0,0 @@
|
|||||||
- title t('.title')
|
|
||||||
|
|
||||||
- content_for :submenu do
|
|
||||||
= render 'admin/shared/menu/settings'
|
|
||||||
|
|
||||||
- content_for :buttons do
|
|
||||||
= admin_button_tag :new, new_admin_layout_url, :class => 'new'
|
|
||||||
|
|
||||||
%p!= t('.help')
|
|
||||||
|
|
||||||
- if @layouts.empty?
|
|
||||||
%p.no-items!= t('.no_items', :url => new_admin_layout_url)
|
|
||||||
- else
|
|
||||||
%ul#layouts-list.list
|
|
||||||
= render @layouts
|
|
@ -1,12 +0,0 @@
|
|||||||
- title t('.title')
|
|
||||||
|
|
||||||
- content_for :submenu do
|
|
||||||
= render 'admin/shared/menu/settings'
|
|
||||||
|
|
||||||
%p!= t('.help')
|
|
||||||
|
|
||||||
= semantic_form_for @layout, :url => admin_layouts_url do |form|
|
|
||||||
|
|
||||||
= render 'form', :f => form
|
|
||||||
|
|
||||||
= render 'admin/shared/form_actions', :back_url => admin_layouts_url, :button_label => :create
|
|
@ -6,8 +6,6 @@
|
|||||||
|
|
||||||
= f.input :title
|
= f.input :title
|
||||||
|
|
||||||
/ = f.input :layout_id, :as => :select, :collection => current_site.layouts.all.to_a, :input_html => { :data_url => admin_layout_page_parts_url('_id_to_replace_') }
|
|
||||||
|
|
||||||
- if not @page.index? and not @page.not_found?
|
- if not @page.index? and not @page.not_found?
|
||||||
= f.input :parent_id, :as => :select, :collection => parent_pages_options, :include_blank => false
|
= f.input :parent_id, :as => :select, :collection => parent_pages_options, :include_blank => false
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
%ul
|
%ul
|
||||||
= admin_submenu_item 'site', edit_admin_current_site_url
|
= admin_submenu_item 'site', edit_admin_current_site_url
|
||||||
/ = admin_submenu_item 'layouts', admin_layouts_url
|
|
||||||
= admin_submenu_item 'snippets', admin_snippets_url
|
= admin_submenu_item 'snippets', admin_snippets_url
|
||||||
= admin_submenu_item 'theme_assets', admin_theme_assets_url
|
= admin_submenu_item 'theme_assets', admin_theme_assets_url
|
||||||
= admin_submenu_item 'account', edit_admin_my_account_url
|
= admin_submenu_item 'account', edit_admin_my_account_url
|
@ -20,7 +20,6 @@ en:
|
|||||||
assets: Assets
|
assets: Assets
|
||||||
settings: Settings
|
settings: Settings
|
||||||
pages: Pages
|
pages: Pages
|
||||||
layouts: Layouts
|
|
||||||
snippets: Snippets
|
snippets: Snippets
|
||||||
account: My account
|
account: My account
|
||||||
site: Site
|
site: Site
|
||||||
@ -108,22 +107,6 @@ en:
|
|||||||
week: 1 week
|
week: 1 week
|
||||||
month: 1 month
|
month: 1 month
|
||||||
|
|
||||||
layouts:
|
|
||||||
index:
|
|
||||||
title: Listing layouts
|
|
||||||
help: "Layouts give the look of a page (1, 2 or many columns)."
|
|
||||||
no_items: "There are no layouts for now. Just click <a href=\"%{url}\">here</a> to create the first one."
|
|
||||||
new: new layout
|
|
||||||
new:
|
|
||||||
title: New layout
|
|
||||||
help: "Fill in the form below to create your layout."
|
|
||||||
edit:
|
|
||||||
title: Editing layout
|
|
||||||
help: "Fill in the form below to update your layout."
|
|
||||||
new: new layout
|
|
||||||
layout:
|
|
||||||
updated_at: Updated at
|
|
||||||
|
|
||||||
snippets:
|
snippets:
|
||||||
index:
|
index:
|
||||||
title: Listing snippets
|
title: Listing snippets
|
||||||
@ -291,7 +274,7 @@ en:
|
|||||||
cache_strategy: "Cache the page for better performance. The 'Simple' choice is a good compromise."
|
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."
|
templatized: "Use the page as a template for a model you defined."
|
||||||
snippet:
|
snippet:
|
||||||
slug: "You need to know it in order to insert the snippet inside a page or a layout"
|
slug: "You need to know it in order to insert the snippet inside a page"
|
||||||
site:
|
site:
|
||||||
meta_keywords: "Meta keywords used within the head tag of the page. They are separeted by an empty space. Required for SEO."
|
meta_keywords: "Meta keywords used within the head tag of the page. They are separeted by an empty space. Required for SEO."
|
||||||
meta_description: "Meta description used within the head tag of the page. Required for SEO."
|
meta_description: "Meta description used within the head tag of the page. Required for SEO."
|
||||||
|
@ -30,7 +30,6 @@ fr:
|
|||||||
assets: Média
|
assets: Média
|
||||||
settings: Paramètres
|
settings: Paramètres
|
||||||
pages: Pages
|
pages: Pages
|
||||||
layouts: Gabarits
|
|
||||||
snippets: Snippets
|
snippets: Snippets
|
||||||
account: Mon compte
|
account: Mon compte
|
||||||
site: Site
|
site: Site
|
||||||
@ -108,22 +107,6 @@ fr:
|
|||||||
week: 1 semaine
|
week: 1 semaine
|
||||||
month: 1 mois
|
month: 1 mois
|
||||||
|
|
||||||
layouts:
|
|
||||||
index:
|
|
||||||
title: Liste gabarits
|
|
||||||
help: "Les gabarits permettent de définir le squelette d'une page (1, 2 ou plusieurs colonnes)."
|
|
||||||
no_items: "Il n'existe pas de gabarit. Vous pouvez commencer par créer un <a href='%{url}'>ici</a>."
|
|
||||||
new: nouveau gabarit
|
|
||||||
new:
|
|
||||||
title: Nouveau gabarit
|
|
||||||
help: "Remplissez le formulaire ci-dessous pour créer votre gabarit."
|
|
||||||
edit:
|
|
||||||
title: Edition gabarit
|
|
||||||
help: "Remplissez le formulaire ci-dessous pour mettre à jour votre gabarit."
|
|
||||||
new: nouveau gabarit
|
|
||||||
layout:
|
|
||||||
updated_at: Mis à jour le
|
|
||||||
|
|
||||||
snippets:
|
snippets:
|
||||||
index:
|
index:
|
||||||
title: Liste des snippets
|
title: Liste des snippets
|
||||||
@ -290,7 +273,7 @@ fr:
|
|||||||
cache_strategy: "Cache la page pour de meilleure performance. L'option 'Simple' est le meilleur compromis."
|
cache_strategy: "Cache la page pour de meilleure performance. L'option 'Simple' est le meilleur compromis."
|
||||||
templatized: "Utilise la page comme un template pour un modèle défini."
|
templatized: "Utilise la page comme un template pour un modèle défini."
|
||||||
snippet:
|
snippet:
|
||||||
slug: "Utilisé pour insérer le snippet dans une page ou un gabarit."
|
slug: "Utilisé pour insérer le snippet dans une page."
|
||||||
site:
|
site:
|
||||||
meta_keywords: "Mots-clés utilisés à l'intérieur de la balise HEAD. Ils sont séparés par un espace. Requis pour un meilleur référencement."
|
meta_keywords: "Mots-clés utilisés à l'intérieur de la balise HEAD. Ils sont séparés par un espace. Requis pour un meilleur référencement."
|
||||||
meta_description: "Description utilisée à l'intérieur de la balise HEAD. Requis pour un meilleur référencement."
|
meta_description: "Description utilisée à l'intérieur de la balise HEAD. Requis pour un meilleur référencement."
|
||||||
|
@ -7,7 +7,6 @@ en:
|
|||||||
messages:
|
messages:
|
||||||
domain_taken: "%{value} is already taken"
|
domain_taken: "%{value} is already taken"
|
||||||
invalid_domain: "%{value} is invalid"
|
invalid_domain: "%{value} is invalid"
|
||||||
missing_content_for_layout: "should contain 'content_for_layout' liquid tag"
|
|
||||||
needs_admin_account: "One admin account is required at least"
|
needs_admin_account: "One admin account is required at least"
|
||||||
protected_page: "You can not remove index or 404 pages"
|
protected_page: "You can not remove index or 404 pages"
|
||||||
extname_changed: "New file does not have the original extension"
|
extname_changed: "New file does not have the original extension"
|
||||||
|
@ -28,7 +28,6 @@ fr:
|
|||||||
|
|
||||||
domain_taken: "%{value} a été déjà pris"
|
domain_taken: "%{value} a été déjà pris"
|
||||||
invalid_domain: "%{value} n'est pas valide"
|
invalid_domain: "%{value} n'est pas valide"
|
||||||
missing_content_for_layout: "doit contenir le tag liquid 'content_for_layout'"
|
|
||||||
needs_admin_account: "Un minimum d'un scompte admin est requis"
|
needs_admin_account: "Un minimum d'un scompte admin est requis"
|
||||||
protected_page: "Vous ne pouvez pas supprimer les pages index et 404"
|
protected_page: "Vous ne pouvez pas supprimer les pages index et 404"
|
||||||
extname_changed: "Nouveau fichier n'a pas l'extension original"
|
extname_changed: "Nouveau fichier n'a pas l'extension original"
|
||||||
@ -53,7 +52,6 @@ fr:
|
|||||||
attributes:
|
attributes:
|
||||||
page:
|
page:
|
||||||
title: Titre
|
title: Titre
|
||||||
layout_id: Gabarit
|
|
||||||
parent: Parent
|
parent: Parent
|
||||||
slug: Raccourci
|
slug: Raccourci
|
||||||
templatized: Templatisée
|
templatized: Templatisée
|
||||||
@ -79,9 +77,6 @@ fr:
|
|||||||
language: Langue
|
language: Langue
|
||||||
new_password: "Nouveau mot de passe"
|
new_password: "Nouveau mot de passe"
|
||||||
new_password_confirmation: "Confirmation nouveau mot de passe"
|
new_password_confirmation: "Confirmation nouveau mot de passe"
|
||||||
layout:
|
|
||||||
name: Nom
|
|
||||||
body: Code
|
|
||||||
snippet:
|
snippet:
|
||||||
body: Code
|
body: Code
|
||||||
slug: Raccourci
|
slug: Raccourci
|
||||||
|
@ -40,16 +40,6 @@ en:
|
|||||||
notice: "My site was successfully updated."
|
notice: "My site was successfully updated."
|
||||||
alert: "My site was not updated."
|
alert: "My site was not updated."
|
||||||
|
|
||||||
layouts:
|
|
||||||
create:
|
|
||||||
notice: "Layout was successfully created."
|
|
||||||
alert: "Layout was not created."
|
|
||||||
update:
|
|
||||||
notice: "Layout was successfully updated."
|
|
||||||
alert: "Layout was not updated."
|
|
||||||
destroy:
|
|
||||||
notice: "Layout was successfully deleted."
|
|
||||||
|
|
||||||
snippets:
|
snippets:
|
||||||
create:
|
create:
|
||||||
notice: "Snippet was successfully created."
|
notice: "Snippet was successfully created."
|
||||||
|
@ -40,16 +40,6 @@ fr:
|
|||||||
notice: "Mon site a été mis à jour avec succès."
|
notice: "Mon site a été mis à jour avec succès."
|
||||||
alert: "Mon site n'a pas été mis à jour."
|
alert: "Mon site n'a pas été mis à jour."
|
||||||
|
|
||||||
layouts:
|
|
||||||
create:
|
|
||||||
notice: "Le gabarit a été crée avec succès."
|
|
||||||
alert: "Le gabarit n'a pas été crée."
|
|
||||||
update:
|
|
||||||
notice: "Le gabarit a été mis à jour avec succès."
|
|
||||||
alert: "Le gabarit n'a pas été mis à jour."
|
|
||||||
destroy:
|
|
||||||
notice: "Le gabarit a été supprimé avec succès."
|
|
||||||
|
|
||||||
snippets:
|
snippets:
|
||||||
create:
|
create:
|
||||||
notice: "Le snippet a été crée avec succès."
|
notice: "Le snippet a été crée avec succès."
|
||||||
|
@ -17,9 +17,6 @@ Rails.application.routes.draw do
|
|||||||
get :get_path, :on => :collection
|
get :get_path, :on => :collection
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :layouts do
|
|
||||||
resources :page_parts, :only => :index
|
|
||||||
end
|
|
||||||
resources :snippets
|
resources :snippets
|
||||||
|
|
||||||
resources :sites
|
resources :sites
|
||||||
|
@ -18,7 +18,7 @@ Scenario: Creating a valid page
|
|||||||
And I fill in "Title" with "Test"
|
And I fill in "Title" with "Test"
|
||||||
And I fill in "Slug" with "test"
|
And I fill in "Slug" with "test"
|
||||||
And I select "Home page" from "Parent"
|
And I select "Home page" from "Parent"
|
||||||
And I fill in "Body" with "Lorem ipsum...."
|
And I fill in "Layout Template" with "Lorem ipsum...."
|
||||||
And I press "Create"
|
And I press "Create"
|
||||||
Then I should see "Page was successfully created."
|
Then I should see "Page was successfully created."
|
||||||
And I should have "Lorem ipsum...." in the test page layout
|
And I should have "Lorem ipsum...." in the test page layout
|
||||||
@ -27,7 +27,7 @@ Scenario: Updating a valid page
|
|||||||
When I go to pages
|
When I go to pages
|
||||||
And I follow "Home page"
|
And I follow "Home page"
|
||||||
And I fill in "Title" with "Home page !"
|
And I fill in "Title" with "Home page !"
|
||||||
And I fill in "Body" with "My new content is here"
|
And I fill in "Layout Template" with "My new content is here"
|
||||||
And I press "Update"
|
And I press "Update"
|
||||||
Then I should see "Page was successfully updated."
|
Then I should see "Page was successfully updated."
|
||||||
And I should have "My new content is here" in the index page layout
|
And I should have "My new content is here" in the index page layout
|
||||||
|
@ -27,13 +27,13 @@ end
|
|||||||
|
|
||||||
### Common
|
### Common
|
||||||
|
|
||||||
def create_layout_samples
|
# def create_layout_samples
|
||||||
Factory(:layout, :site => @site, :name => 'One column', :value => %{<html>
|
# Factory(:layout, :site => @site, :name => 'One column', :value => %{<html>
|
||||||
<head>
|
# <head>
|
||||||
<title>My website</title>
|
# <title>My website</title>
|
||||||
</head>
|
# </head>
|
||||||
<body>
|
# <body>
|
||||||
<div id="main">{{ content_for_layout }}</div>
|
# <div id="main">{{ content_for_layout }}</div>
|
||||||
</body>
|
# </body>
|
||||||
</html>})
|
# </html>})
|
||||||
end
|
# end
|
||||||
|
@ -17,29 +17,24 @@ Given /^a page named "([^"]*)" with the template:$/ do |page_slug, template|
|
|||||||
@page = create_content_page(page_slug, '', template)
|
@page = create_content_page(page_slug, '', template)
|
||||||
end
|
end
|
||||||
|
|
||||||
# creates a layout
|
# # creates a part within a page
|
||||||
Given /^a layout named "([^"]*)" with the source:$/ do |layout_name, layout_body|
|
# Given /^the page named "([^"]*)" has the part "([^"]*)" with the content:$/ do |page_slug, part_slug, part_contents|
|
||||||
@layout = Factory(:layout, :name => layout_name, :value => layout_body, :site => @site)
|
# page = @site.pages.where(:slug => page_slug).first
|
||||||
end
|
# raise "Could not find page: #{page_slug}" unless page
|
||||||
|
#
|
||||||
# creates a part within a page
|
# # find or crate page part
|
||||||
Given /^the page named "([^"]*)" has the part "([^"]*)" with the content:$/ do |page_slug, part_slug, part_contents|
|
# part = page.parts.where(:slug => part_slug).first
|
||||||
page = @site.pages.where(:slug => page_slug).first
|
# unless part
|
||||||
raise "Could not find page: #{page_slug}" unless page
|
# part = page.parts.build(:name => part_slug.titleize, :slug => part_slug)
|
||||||
|
# end
|
||||||
# find or crate page part
|
#
|
||||||
part = page.parts.where(:slug => part_slug).first
|
# # set part value
|
||||||
unless part
|
# part.value = part_contents
|
||||||
part = page.parts.build(:name => part_slug.titleize, :slug => part_slug)
|
# part.should be_valid
|
||||||
end
|
#
|
||||||
|
# # save page with embedded part
|
||||||
# set part value
|
# page.save
|
||||||
part.value = part_contents
|
# end
|
||||||
part.should be_valid
|
|
||||||
|
|
||||||
# save page with embedded part
|
|
||||||
page.save
|
|
||||||
end
|
|
||||||
|
|
||||||
# try to render a page by slug
|
# try to render a page by slug
|
||||||
When /^I view the rendered page at "([^"]*)"$/ do |path|
|
When /^I view the rendered page at "([^"]*)"$/ do |path|
|
||||||
|
@ -5,9 +5,5 @@ module Locomotive
|
|||||||
|
|
||||||
DOMAIN = /^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix
|
DOMAIN = /^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix
|
||||||
|
|
||||||
CONTENT_FOR = /\{\{\s*content_for_([a-zA-Z]{1}[a-zA-Z_0-9]*)(\s+.*)?\s*\}\}/
|
|
||||||
|
|
||||||
CONTENT_FOR_LAYOUT = /\{\{\s*content_for_layout\s*/
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
$(document).ready(function() {
|
|
||||||
$('a#image-picker-link').imagepicker({
|
|
||||||
insertFn: function(link) {
|
|
||||||
return "{{ theme_images." + link.attr('data-slug') + " }}";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
@ -17,8 +17,9 @@ $(document).ready(function() {
|
|||||||
var newRow = lastRow.clone(true).removeClass('template').addClass('added').insertBefore(lastRow);
|
var newRow = lastRow.clone(true).removeClass('template').addClass('added').insertBefore(lastRow);
|
||||||
|
|
||||||
// should copy the value of the select box
|
// should copy the value of the select box
|
||||||
|
var input_name = $('input#current_site_subdomain').attr('name').split('[')[0];
|
||||||
var input = newRow.find('input.label')
|
var input = newRow.find('input.label')
|
||||||
.attr('name', 'site[domains][]');
|
.attr('name', input_name + '[domains][]');
|
||||||
if (lastRow.find('input.label').val() == '') input.val("undefined");
|
if (lastRow.find('input.label').val() == '') input.val("undefined");
|
||||||
|
|
||||||
// then reset the form
|
// then reset the form
|
||||||
|
@ -67,41 +67,41 @@ Factory.define :liquid_template do |t|
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
## Layouts ##
|
# ## Layouts ##
|
||||||
Factory.define :layout do |l|
|
# Factory.define :layout do |l|
|
||||||
l.name '1 main column + sidebar'
|
# l.name '1 main column + sidebar'
|
||||||
l.value %{<html>
|
# l.value %{<html>
|
||||||
<head>
|
# <head>
|
||||||
<title>My website</title>
|
# <title>My website</title>
|
||||||
</head>
|
# </head>
|
||||||
<body>
|
# <body>
|
||||||
<div id="sidebar">
|
# <div id="sidebar">
|
||||||
\{% block sidebar %\}
|
# \{% block sidebar %\}
|
||||||
DEFAULT SIDEBAR CONTENT
|
# DEFAULT SIDEBAR CONTENT
|
||||||
\{% endblock %\}
|
# \{% endblock %\}
|
||||||
</div>
|
# </div>
|
||||||
<div id="main">
|
# <div id="main">
|
||||||
\{% block main %\}
|
# \{% block main %\}
|
||||||
DEFAULT MAIN CONTENT
|
# DEFAULT MAIN CONTENT
|
||||||
\{% endblock %\}
|
# \{% endblock %\}
|
||||||
</div>
|
# </div>
|
||||||
</body>
|
# </body>
|
||||||
</html>}
|
# </html>}
|
||||||
l.site { Site.where(:subdomain => "acme").first || Factory(:site) }
|
# l.site { Site.where(:subdomain => "acme").first || Factory(:site) }
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
Factory.define :base_layout, :parent => :layout do |l|
|
# Factory.define :base_layout, :parent => :layout do |l|
|
||||||
l.name '1 main column + sidebar'
|
# l.name '1 main column + sidebar'
|
||||||
l.value %{<html>
|
# l.value %{<html>
|
||||||
<head>
|
# <head>
|
||||||
<title>My website</title>
|
# <title>My website</title>
|
||||||
</head>
|
# </head>
|
||||||
<body>
|
# <body>
|
||||||
<div id="sidebar">\{\{ content_for_left_sidebar \}\}</div>
|
# <div id="sidebar">\{\{ content_for_left_sidebar \}\}</div>
|
||||||
<div id="main">\{\{ content_for_layout | textile \}\}</div>
|
# <div id="main">\{\{ content_for_layout | textile \}\}</div>
|
||||||
</body>
|
# </body>
|
||||||
</html>}
|
# </html>}
|
||||||
end
|
# end
|
||||||
|
|
||||||
|
|
||||||
## Snippets ##
|
## Snippets ##
|
||||||
|
@ -7,21 +7,21 @@ describe Locomotive::Liquid::Tags::Consume do
|
|||||||
it 'validates a basic syntax' do
|
it 'validates a basic syntax' do
|
||||||
markup = 'blog from "http://blog.locomotiveapp.org"'
|
markup = 'blog from "http://blog.locomotiveapp.org"'
|
||||||
lambda do
|
lambda do
|
||||||
Locomotive::Liquid::Tags::Consume.new('consume', markup, ["{% endconsume %}"])
|
Locomotive::Liquid::Tags::Consume.new('consume', markup, ["{% endconsume %}"], {})
|
||||||
end.should_not raise_error
|
end.should_not raise_error
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'validates more complex syntax with attributes' do
|
it 'validates more complex syntax with attributes' do
|
||||||
markup = 'blog from "http://www.locomotiveapp.org" username: "john", password: "easyone"'
|
markup = 'blog from "http://www.locomotiveapp.org" username: "john", password: "easyone"'
|
||||||
lambda do
|
lambda do
|
||||||
Locomotive::Liquid::Tags::Consume.new('consume', markup, ["{% endconsume %}"])
|
Locomotive::Liquid::Tags::Consume.new('consume', markup, ["{% endconsume %}"], {})
|
||||||
end.should_not raise_error
|
end.should_not raise_error
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'raises an error if the syntax is incorrect' do
|
it 'raises an error if the syntax is incorrect' do
|
||||||
markup = 'blog from http://www.locomotiveapp.org'
|
markup = 'blog from http://www.locomotiveapp.org'
|
||||||
lambda do
|
lambda do
|
||||||
Locomotive::Liquid::Tags::Consume.new('consume', markup, ["{% endconsume %}"])
|
Locomotive::Liquid::Tags::Consume.new('consume', markup, ["{% endconsume %}"], {})
|
||||||
end.should raise_error
|
end.should raise_error
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -5,14 +5,14 @@ describe Locomotive::Liquid::Tags::Paginate do
|
|||||||
it 'should have a valid syntax' do
|
it 'should have a valid syntax' do
|
||||||
markup = "contents.projects by 5"
|
markup = "contents.projects by 5"
|
||||||
lambda do
|
lambda do
|
||||||
Locomotive::Liquid::Tags::Paginate.new('paginate', markup, ["{% endpaginate %}"])
|
Locomotive::Liquid::Tags::Paginate.new('paginate', markup, ["{% endpaginate %}"], {})
|
||||||
end.should_not raise_error
|
end.should_not raise_error
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should raise an error if the syntax is incorrect' do
|
it 'should raise an error if the syntax is incorrect' do
|
||||||
["contents.projects by a", "contents.projects", "contents.projects 5"].each do |markup|
|
["contents.projects by a", "contents.projects", "contents.projects 5"].each do |markup|
|
||||||
lambda do
|
lambda do
|
||||||
Locomotive::Liquid::Tags::Paginate.new('paginate', markup, ["{% endpaginate %}"])
|
Locomotive::Liquid::Tags::Paginate.new('paginate', markup, ["{% endpaginate %}"], {})
|
||||||
end.should raise_error
|
end.should raise_error
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -3,7 +3,7 @@ require 'spec_helper'
|
|||||||
describe Locomotive::Liquid::Tags::WithScope do
|
describe Locomotive::Liquid::Tags::WithScope do
|
||||||
|
|
||||||
it 'should decode options (boolean, interger, ...)' do
|
it 'should decode options (boolean, interger, ...)' do
|
||||||
scope = Locomotive::Liquid::Tags::WithScope.new('with_scope', 'active:true price:42 title:\'foo\' hidden:false', ["{% endwith_scope %}"])
|
scope = Locomotive::Liquid::Tags::WithScope.new('with_scope', 'active:true price:42 title:\'foo\' hidden:false', ["{% endwith_scope %}"], {})
|
||||||
attributes = scope.send(:decode, scope.instance_variable_get(:@attributes))
|
attributes = scope.send(:decode, scope.instance_variable_get(:@attributes))
|
||||||
attributes['active'].should == true
|
attributes['active'].should == true
|
||||||
attributes['price'].should == 42
|
attributes['price'].should == 42
|
||||||
|
@ -1,64 +0,0 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe Layout do
|
|
||||||
|
|
||||||
it 'should have a valid factory' do
|
|
||||||
Factory.build(:layout).should be_valid
|
|
||||||
end
|
|
||||||
|
|
||||||
# ## validations ##
|
|
||||||
#
|
|
||||||
# it 'should validate presence of content_for_layout in value' do
|
|
||||||
# layout = Factory.build(:layout, :value => 'without content_for_layout')
|
|
||||||
# layout.should_not be_valid
|
|
||||||
# layout.errors[:value].should == ["should contain 'content_for_layout' liquid tag"]
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# context 'dealing with page parts' do
|
|
||||||
#
|
|
||||||
# before(:each) do
|
|
||||||
# @layout = Factory.build(:layout)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# it 'should have 2 parts' do
|
|
||||||
# @layout.send(:build_parts_from_value)
|
|
||||||
# @layout.parts.size.should == 2
|
|
||||||
#
|
|
||||||
# @layout.parts.first.name.should == 'Body'
|
|
||||||
# @layout.parts.first.slug.should == 'layout'
|
|
||||||
#
|
|
||||||
# @layout.parts.last.name.should == 'Left sidebar'
|
|
||||||
# @layout.parts.last.slug.should == 'left_sidebar'
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# it 'should not add parts to pages if layout does not change' do
|
|
||||||
# @layout.stubs(:value_changed?).returns(false)
|
|
||||||
# page = Factory.build(:page, :layout => @layout, :site => nil)
|
|
||||||
# page.expects(:update_parts!).never
|
|
||||||
# @layout.pages << page
|
|
||||||
# @layout.save
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# it 'should add parts to pages if layout changes' do
|
|
||||||
# @layout.value = @layout.value + "..."
|
|
||||||
# page = Factory.build(:page, :layout => @layout, :site => nil)
|
|
||||||
# page.expects(:update_parts!)
|
|
||||||
# @layout.pages << page
|
|
||||||
# @layout.save
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# context 'parsing liquid template' do
|
|
||||||
#
|
|
||||||
# before(:each) do
|
|
||||||
# @layout = Factory.build(:layout)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# it 'should not raise an error if template is empty' do
|
|
||||||
# @layout.template.should be_nil
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# end
|
|
||||||
|
|
||||||
end
|
|
@ -105,120 +105,6 @@ describe Page do
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'accepts_nested_attributes_for used for parts' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@page = Factory.build(:page)
|
|
||||||
@page.parts.build(:name => 'Main content', :slug => 'layout')
|
|
||||||
@page.parts.build(:name => 'Left column', :slug => 'left_sidebar')
|
|
||||||
@page.parts.build(:name => 'Right column', :slug => 'right_sidebar')
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should add parts' do
|
|
||||||
attributes = { '0' => { 'slug' => 'footer', 'name' => 'A custom footer', 'value' => 'End of page' } }
|
|
||||||
@page.parts_attributes = attributes
|
|
||||||
@page.parts.size.should == 4
|
|
||||||
@page.parts.last.slug.should == 'footer'
|
|
||||||
@page.parts.last.disabled.should == false
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should update parts' do
|
|
||||||
attributes = { '0' => { 'slug' => 'layout', 'name' => 'A new name', 'value' => 'Hello world' } }
|
|
||||||
@page.parts_attributes = attributes
|
|
||||||
@page.parts.size.should == 3
|
|
||||||
@page.parts.first.slug.should == 'layout'
|
|
||||||
@page.parts.first.name.should == 'A new name'
|
|
||||||
@page.parts.first.value.should == 'Hello world'
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should disable parts' do
|
|
||||||
attributes = { '0' => { 'slug' => 'left_sidebar', 'disabled' => 'true' } }
|
|
||||||
@page.parts_attributes = attributes
|
|
||||||
@page.parts.size.should == 3
|
|
||||||
@page.parts.first.disabled.should == true
|
|
||||||
@page.parts[1].disabled.should == true
|
|
||||||
@page.parts[2].disabled.should == true
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should add/update/disable parts at the same time' do
|
|
||||||
@page.parts.size.should == 3
|
|
||||||
|
|
||||||
attributes = {
|
|
||||||
'0' => { 'slug' => 'layout', 'name' => 'Body', 'value' => 'Hello world' },
|
|
||||||
'1' => { 'slug' => 'left_sidebar', 'disabled' => 'true' },
|
|
||||||
'2' => { 'id' => @page.parts[2].id, 'value' => 'Content from right sidebar', 'disabled' => 'false' }
|
|
||||||
}
|
|
||||||
@page.parts_attributes = attributes
|
|
||||||
@page.parts.size.should == 3
|
|
||||||
|
|
||||||
@page.parts[0].value.should == 'Hello world'
|
|
||||||
@page.parts[1].disabled.should == true
|
|
||||||
@page.parts[2].disabled.should == false
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should update it with success (mongoid bug #71)' do
|
|
||||||
@page.save
|
|
||||||
@page = Page.first
|
|
||||||
|
|
||||||
@page.parts.size.should == 3
|
|
||||||
@page.parts_attributes = { '0' => { 'slug' => 'header', 'name' => 'A custom header', 'value' => 'Head of page' } }
|
|
||||||
@page.parts.size.should == 4
|
|
||||||
|
|
||||||
@page.save
|
|
||||||
@page = Page.first
|
|
||||||
|
|
||||||
@page.parts.size.should == 4
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'dealing with page parts' do # DUPLICATED ?
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@page = Factory.build(:page)
|
|
||||||
@parts = [
|
|
||||||
PagePart.new(:name => 'Main content', :slug => 'layout'),
|
|
||||||
PagePart.new(:name => 'Left column', :slug => 'left_sidebar'),
|
|
||||||
PagePart.new(:name => 'Right column', :slug => 'right_sidebar')
|
|
||||||
]
|
|
||||||
@page.send(:update_parts, @parts)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should add new parts from an array of parts' do
|
|
||||||
@page.parts.size.should == 3
|
|
||||||
@page.parts.shift.name.should == 'Main content'
|
|
||||||
@page.parts.shift.name.should == 'Left column'
|
|
||||||
@page.parts.shift.name.should == 'Right column'
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should update parts' do
|
|
||||||
@parts[1].name = 'Very left column'
|
|
||||||
@page.send(:update_parts, @parts)
|
|
||||||
@page.parts.size.should == 3
|
|
||||||
@page.parts[1].name.should == 'Very left column'
|
|
||||||
@page.parts[1].slug.should == 'left_sidebar'
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should disable parts' do
|
|
||||||
@parts = [@parts.shift, @parts.pop]
|
|
||||||
@page.send(:update_parts, @parts)
|
|
||||||
@page.parts.size.should == 3
|
|
||||||
@page.parts[1].name.should == 'Left column'
|
|
||||||
@page.parts[1].disabled.should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should enable parts previously disabled' do
|
|
||||||
parts_at_first = @parts.clone
|
|
||||||
@parts = [@parts.shift, @parts.pop]
|
|
||||||
@page.send(:update_parts, @parts)
|
|
||||||
@page.send(:update_parts, parts_at_first)
|
|
||||||
@page.parts.size.should == 3
|
|
||||||
@page.parts[1].name.should == 'Left column'
|
|
||||||
@page.parts[1].disabled.should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'acts as tree' do
|
describe 'acts as tree' do
|
||||||
|
|
||||||
before(:each) do
|
before(:each) do
|
||||||
@ -295,71 +181,6 @@ describe Page do
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'rendering' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@page = Factory.build(:page, :site => nil)
|
|
||||||
@page.parts.build :slug => 'layout', :value => 'Hello world !'
|
|
||||||
@page.parts.build :slug => 'left_sidebar', :value => 'A sidebar...'
|
|
||||||
@page.send(:store_template)
|
|
||||||
@layout = Factory.build(:layout, :site => nil)
|
|
||||||
@layout.send(:store_template)
|
|
||||||
@context = Liquid::Context.new
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'without layout' do
|
|
||||||
|
|
||||||
it 'should render the body part' do
|
|
||||||
@page.render(@context).should == 'Hello world !'
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with layout' do
|
|
||||||
|
|
||||||
it 'should render both the body and sidebar parts' do
|
|
||||||
@page.layout = @layout
|
|
||||||
@page.render(@context).should == %{<html>
|
|
||||||
<head>
|
|
||||||
<title>My website</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="sidebar">A sidebar...</div>
|
|
||||||
<div id="main"><p>Hello world !</p></div>
|
|
||||||
</body>
|
|
||||||
</html>}
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
describe "creating a new page" do
|
|
||||||
|
|
||||||
context "with a body" do
|
|
||||||
before do
|
|
||||||
@site = Factory(:site, :subdomain => "somethingweird")
|
|
||||||
@page = Page.create({
|
|
||||||
:slug => "some_slug",
|
|
||||||
:title => "Page Title",
|
|
||||||
:body => "Page Body",
|
|
||||||
:published => true,
|
|
||||||
:site => @site
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should be valid" do
|
|
||||||
@page.should be_valid
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should render the passed in body attribute of the page" do
|
|
||||||
@page.render(Liquid::Context.new).should == "Page Body"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
describe 'templatized extension' do
|
describe 'templatized extension' do
|
||||||
|
|
||||||
before(:each) do
|
before(:each) do
|
||||||
|
@ -121,25 +121,16 @@ describe Site do
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'delete in cascade' do
|
describe 'deleting in cascade' do
|
||||||
|
|
||||||
before(:each) do
|
before(:each) do
|
||||||
@site = Factory(:site)
|
@site = Factory(:site)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should destroy pages' do
|
it 'should also destroy pages' do
|
||||||
@site.pages.expects(:destroy_all)
|
lambda {
|
||||||
@site.destroy
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should destroy layouts' do
|
|
||||||
@site.layouts.expects(:destroy_all)
|
|
||||||
@site.destroy
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should destroy snippets' do
|
|
||||||
@site.snippets.expects(:destroy_all)
|
|
||||||
@site.destroy
|
@site.destroy
|
||||||
|
}.should change(Page, :count).by(-2)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
3
vendor/plugins/custom_fields/.rspec
vendored
3
vendor/plugins/custom_fields/.rspec
vendored
@ -1,3 +0,0 @@
|
|||||||
--colour
|
|
||||||
--format nested
|
|
||||||
--backtrace
|
|
12
vendor/plugins/custom_fields/Gemfile
vendored
12
vendor/plugins/custom_fields/Gemfile
vendored
@ -1,12 +0,0 @@
|
|||||||
source 'http://gemcutter.org'
|
|
||||||
|
|
||||||
gem 'bson_ext', '>= 1.0.1'
|
|
||||||
gem 'mongo_ext'
|
|
||||||
gem 'mongoid', '2.0.0.beta.14'
|
|
||||||
gem 'activesupport', '~>3.0.0.beta'
|
|
||||||
gem 'carrierwave-rails3', :require => 'carrierwave'
|
|
||||||
|
|
||||||
group :test do
|
|
||||||
gem 'rspec', '>= 2.0.0.beta.10'
|
|
||||||
gem 'mocha', :git => 'git://github.com/floehopper/mocha.git'
|
|
||||||
end
|
|
20
vendor/plugins/custom_fields/MIT-LICENSE
vendored
20
vendor/plugins/custom_fields/MIT-LICENSE
vendored
@ -1,20 +0,0 @@
|
|||||||
Copyright (c) 2010 [name of plugin creator]
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
13
vendor/plugins/custom_fields/README
vendored
13
vendor/plugins/custom_fields/README
vendored
@ -1,13 +0,0 @@
|
|||||||
CustomFields
|
|
||||||
===========
|
|
||||||
|
|
||||||
Introduction goes here.
|
|
||||||
|
|
||||||
|
|
||||||
Example
|
|
||||||
=======
|
|
||||||
|
|
||||||
Example goes here.
|
|
||||||
|
|
||||||
|
|
||||||
Copyright (c) 2010 [Didier Lafforgue], released under the MIT license
|
|
29
vendor/plugins/custom_fields/Rakefile
vendored
29
vendor/plugins/custom_fields/Rakefile
vendored
@ -1,29 +0,0 @@
|
|||||||
require "rubygems"
|
|
||||||
require "rake"
|
|
||||||
require "rake/rdoctask"
|
|
||||||
require "rspec"
|
|
||||||
require "rspec/core/rake_task"
|
|
||||||
|
|
||||||
desc 'Generate documentation for the custom_fields plugin.'
|
|
||||||
Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
||||||
rdoc.rdoc_dir = 'rdoc'
|
|
||||||
rdoc.title = 'CustomFields'
|
|
||||||
rdoc.options << '--line-numbers' << '--inline-source'
|
|
||||||
rdoc.rdoc_files.include('README')
|
|
||||||
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
||||||
end
|
|
||||||
|
|
||||||
Rspec::Core::RakeTask.new('spec:unit') do |spec|
|
|
||||||
spec.pattern = "spec/unit/**/*_spec.rb"
|
|
||||||
# spec.pattern = "spec/unit/custom_fields_for_spec.rb"
|
|
||||||
# spec.pattern = "spec/unit/types/category_spec.rb"
|
|
||||||
end
|
|
||||||
|
|
||||||
Rspec::Core::RakeTask.new('spec:integration') do |spec|
|
|
||||||
spec.pattern = "spec/integration/**/*_spec.rb"
|
|
||||||
# spec.pattern = "spec/integration/types/category_spec.rb"
|
|
||||||
end
|
|
||||||
|
|
||||||
task :spec => ['spec:unit', 'spec:integration']
|
|
||||||
|
|
||||||
task :default => :spec
|
|
2
vendor/plugins/custom_fields/init.rb
vendored
2
vendor/plugins/custom_fields/init.rb
vendored
@ -1,2 +0,0 @@
|
|||||||
# Include hook code here
|
|
||||||
require File.dirname(__FILE__) + '/lib/custom_fields'
|
|
@ -1,28 +0,0 @@
|
|||||||
$:.unshift File.expand_path(File.dirname(__FILE__))
|
|
||||||
|
|
||||||
require 'active_support'
|
|
||||||
require 'carrierwave/orm/mongoid'
|
|
||||||
|
|
||||||
require 'custom_fields/extensions/mongoid/hierarchy'
|
|
||||||
require 'custom_fields/extensions/mongoid/associations/proxy'
|
|
||||||
require 'custom_fields/extensions/mongoid/associations/references_many'
|
|
||||||
require 'custom_fields/extensions/mongoid/associations/embeds_many'
|
|
||||||
require 'custom_fields/types/default'
|
|
||||||
require 'custom_fields/types/string'
|
|
||||||
require 'custom_fields/types/text'
|
|
||||||
require 'custom_fields/types/category'
|
|
||||||
require 'custom_fields/types/boolean'
|
|
||||||
require 'custom_fields/types/date'
|
|
||||||
require 'custom_fields/types/file'
|
|
||||||
require 'custom_fields/proxy_class_enabler'
|
|
||||||
require 'custom_fields/field'
|
|
||||||
require 'custom_fields/custom_fields_for'
|
|
||||||
|
|
||||||
module Mongoid
|
|
||||||
module CustomFields
|
|
||||||
extend ActiveSupport::Concern
|
|
||||||
included do
|
|
||||||
include ::CustomFields::CustomFieldsFor
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,50 +0,0 @@
|
|||||||
module CustomFields
|
|
||||||
|
|
||||||
module CustomFieldsFor
|
|
||||||
|
|
||||||
def self.included(base)
|
|
||||||
base.extend(ClassMethods)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Enhance an embedded collection by providing methods to manage custom fields
|
|
||||||
#
|
|
||||||
# class Company
|
|
||||||
# embeds_many :employees
|
|
||||||
# custom_fields_for :employees
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# class Employee
|
|
||||||
# embedded_in :company, :inverse_of => :employees
|
|
||||||
# field :name, String
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# company.employee_custom_fields.build :label => 'His/her position', :_alias => 'position', :kind => 'String'
|
|
||||||
#
|
|
||||||
# company.employees.build :name => 'Michael Scott', :position => 'Regional manager'
|
|
||||||
#
|
|
||||||
module ClassMethods
|
|
||||||
|
|
||||||
def custom_fields_for(collection_name)
|
|
||||||
singular_name = collection_name.to_s.singularize
|
|
||||||
|
|
||||||
class_eval <<-EOV
|
|
||||||
field :#{singular_name}_custom_fields_counter, :type => Integer, :default => 0
|
|
||||||
|
|
||||||
embeds_many :#{singular_name}_custom_fields, :class_name => "::CustomFields::Field"
|
|
||||||
|
|
||||||
validates_associated :#{singular_name}_custom_fields
|
|
||||||
|
|
||||||
accepts_nested_attributes_for :#{singular_name}_custom_fields, :allow_destroy => true
|
|
||||||
|
|
||||||
def ordered_#{singular_name}_custom_fields
|
|
||||||
self.#{singular_name}_custom_fields.sort { |a, b| (a.position || 0) <=> (b.position || 0) }
|
|
||||||
end
|
|
||||||
|
|
||||||
EOV
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
@ -1,31 +0,0 @@
|
|||||||
# encoding: utf-8
|
|
||||||
module Mongoid #:nodoc:
|
|
||||||
module Associations #:nodoc:
|
|
||||||
class EmbedsMany < Proxy
|
|
||||||
|
|
||||||
def initialize_with_custom_fields(parent, options, target_array = nil)
|
|
||||||
if custom_fields?(parent, options.name)
|
|
||||||
options = options.clone # 2 parent instances should not share the exact same option instance
|
|
||||||
|
|
||||||
custom_fields = parent.send(:"ordered_#{custom_fields_association_name(options.name)}")
|
|
||||||
|
|
||||||
klass = options.klass.to_klass_with_custom_fields(custom_fields)
|
|
||||||
klass._parent = parent
|
|
||||||
klass.association_name = options.name
|
|
||||||
|
|
||||||
options.instance_eval <<-EOF
|
|
||||||
def klass=(klass); @klass = klass; end
|
|
||||||
def klass; @klass || class_name.constantize; end
|
|
||||||
EOF
|
|
||||||
|
|
||||||
options.klass = klass
|
|
||||||
end
|
|
||||||
|
|
||||||
initialize_without_custom_fields(parent, options, target_array)
|
|
||||||
end
|
|
||||||
|
|
||||||
alias_method_chain :initialize, :custom_fields
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,20 +0,0 @@
|
|||||||
# encoding: utf-8
|
|
||||||
module Mongoid #:nodoc
|
|
||||||
module Associations #:nodoc
|
|
||||||
class Proxy #:nodoc
|
|
||||||
|
|
||||||
def custom_fields_association_name(association_name)
|
|
||||||
"#{association_name.to_s.singularize}_custom_fields".to_sym
|
|
||||||
end
|
|
||||||
|
|
||||||
def custom_fields?(object, association_name)
|
|
||||||
object.respond_to?(custom_fields_association_name(association_name))
|
|
||||||
end
|
|
||||||
|
|
||||||
def klass
|
|
||||||
@klass
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,33 +0,0 @@
|
|||||||
# encoding: utf-8
|
|
||||||
module Mongoid #:nodoc:
|
|
||||||
module Associations #:nodoc:
|
|
||||||
# Represents an relational one-to-many association with an object in a
|
|
||||||
# separate collection or database.
|
|
||||||
class ReferencesMany < Proxy
|
|
||||||
|
|
||||||
def initialize_with_custom_fields(parent, options, target_array = nil)
|
|
||||||
if custom_fields?(parent, options.name)
|
|
||||||
options = options.clone # 2 parent instances should not share the exact same option instance
|
|
||||||
|
|
||||||
custom_fields = parent.send(:"ordered_#{custom_fields_association_name(options.name)}")
|
|
||||||
|
|
||||||
klass = options.klass.to_klass_with_custom_fields(custom_fields)
|
|
||||||
klass._parent = parent
|
|
||||||
klass.association_name = options.name
|
|
||||||
|
|
||||||
options.instance_eval <<-EOF
|
|
||||||
def klass=(klass); @klass = klass; end
|
|
||||||
def klass; @klass || class_name.constantize; end
|
|
||||||
EOF
|
|
||||||
|
|
||||||
options.klass = klass
|
|
||||||
end
|
|
||||||
|
|
||||||
initialize_without_custom_fields(parent, options, target_array)
|
|
||||||
end
|
|
||||||
|
|
||||||
alias_method_chain :initialize, :custom_fields
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,28 +0,0 @@
|
|||||||
# encoding: utf-8
|
|
||||||
module Mongoid #:nodoc
|
|
||||||
module Hierarchy #:nodoc
|
|
||||||
module InstanceMethods
|
|
||||||
|
|
||||||
def parentize_with_custom_fields(object, association_name)
|
|
||||||
if association_name.to_s.ends_with?('_custom_fields')
|
|
||||||
self.singleton_class.associations = {}
|
|
||||||
self.singleton_class.embedded_in object.class.to_s.underscore.to_sym, :inverse_of => association_name
|
|
||||||
end
|
|
||||||
|
|
||||||
parentize_without_custom_fields(object, association_name)
|
|
||||||
|
|
||||||
if self.embedded? && self.instance_variable_get(:"@association_name").nil?
|
|
||||||
self.instance_variable_set(:"@association_name", association_name) # weird bug with proxy class
|
|
||||||
end
|
|
||||||
|
|
||||||
if association_name.to_s.ends_with?('_custom_fields')
|
|
||||||
self.send(:set_unique_name!)
|
|
||||||
self.send(:set_alias)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
alias_method_chain :parentize, :custom_fields
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,82 +0,0 @@
|
|||||||
module CustomFields
|
|
||||||
|
|
||||||
class Field
|
|
||||||
include ::Mongoid::Document
|
|
||||||
include ::Mongoid::Timestamps
|
|
||||||
|
|
||||||
# types ##
|
|
||||||
include Types::Default
|
|
||||||
include Types::String
|
|
||||||
include Types::Text
|
|
||||||
include Types::Category
|
|
||||||
include Types::Boolean
|
|
||||||
include Types::Date
|
|
||||||
include Types::File
|
|
||||||
|
|
||||||
## fields ##
|
|
||||||
field :label
|
|
||||||
field :_alias
|
|
||||||
field :_name
|
|
||||||
field :kind
|
|
||||||
field :hint
|
|
||||||
field :position, :type => Integer, :default => 0
|
|
||||||
|
|
||||||
## validations ##
|
|
||||||
validates_presence_of :label, :kind
|
|
||||||
validate :uniqueness_of_label
|
|
||||||
|
|
||||||
## methods ##
|
|
||||||
|
|
||||||
def field_type
|
|
||||||
self.class.field_types[self.kind.downcase.to_sym]
|
|
||||||
end
|
|
||||||
|
|
||||||
def apply(klass)
|
|
||||||
return unless self.valid?
|
|
||||||
|
|
||||||
klass.field self._name, :type => self.field_type if self.field_type
|
|
||||||
|
|
||||||
apply_method_name = :"apply_#{self.kind.downcase}_type"
|
|
||||||
|
|
||||||
if self.respond_to?(apply_method_name)
|
|
||||||
self.send(apply_method_name, klass)
|
|
||||||
else
|
|
||||||
apply_default_type(klass)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def safe_alias
|
|
||||||
self.set_alias
|
|
||||||
self._alias
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def uniqueness_of_label
|
|
||||||
duplicate = self.siblings.detect { |f| f.label == self.label && f._id != self._id }
|
|
||||||
if not duplicate.nil?
|
|
||||||
self.errors.add(:label, :taken)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_unique_name!
|
|
||||||
self._name ||= "custom_field_#{self.increment_counter!}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_alias
|
|
||||||
return if self.label.blank? && self._alias.blank?
|
|
||||||
self._alias = (self._alias.blank? ? self.label : self._alias).parameterize('_').downcase
|
|
||||||
end
|
|
||||||
|
|
||||||
def increment_counter!
|
|
||||||
next_value = (self._parent.send(:"#{self.association_name}_counter") || 0) + 1
|
|
||||||
self._parent.send(:"#{self.association_name}_counter=", next_value)
|
|
||||||
next_value
|
|
||||||
end
|
|
||||||
|
|
||||||
def siblings
|
|
||||||
self._parent.send(self.association_name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
@ -1,37 +0,0 @@
|
|||||||
module CustomFields
|
|
||||||
module ProxyClassEnabler
|
|
||||||
|
|
||||||
extend ActiveSupport::Concern
|
|
||||||
|
|
||||||
included do
|
|
||||||
|
|
||||||
cattr_accessor :klass_with_custom_fields
|
|
||||||
|
|
||||||
def self.to_klass_with_custom_fields(fields)
|
|
||||||
return klass_with_custom_fields unless klass_with_custom_fields.nil?
|
|
||||||
|
|
||||||
klass = Class.new(self)
|
|
||||||
klass.class_eval <<-EOF
|
|
||||||
cattr_accessor :custom_fields, :_parent, :association_name
|
|
||||||
|
|
||||||
def self.model_name
|
|
||||||
@_model_name ||= ActiveModel::Name.new(self.superclass)
|
|
||||||
end
|
|
||||||
|
|
||||||
def custom_fields
|
|
||||||
self.class.custom_fields
|
|
||||||
end
|
|
||||||
EOF
|
|
||||||
|
|
||||||
klass.hereditary = false
|
|
||||||
klass.custom_fields = fields
|
|
||||||
|
|
||||||
[*fields].each { |field| field.apply(klass) }
|
|
||||||
|
|
||||||
klass_with_custom_fields = klass
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,29 +0,0 @@
|
|||||||
module CustomFields
|
|
||||||
module Types
|
|
||||||
module Boolean
|
|
||||||
|
|
||||||
extend ActiveSupport::Concern
|
|
||||||
|
|
||||||
included do
|
|
||||||
register_type :boolean
|
|
||||||
end
|
|
||||||
|
|
||||||
module InstanceMethods
|
|
||||||
|
|
||||||
def apply_boolean_type(klass)
|
|
||||||
|
|
||||||
klass.class_eval <<-EOF
|
|
||||||
alias :#{self.safe_alias}= :#{self._name}=
|
|
||||||
|
|
||||||
def #{self.safe_alias}
|
|
||||||
::Boolean.set(read_attribute(:#{self._name}))
|
|
||||||
end
|
|
||||||
EOF
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,85 +0,0 @@
|
|||||||
module CustomFields
|
|
||||||
module Types
|
|
||||||
module Category
|
|
||||||
|
|
||||||
extend ActiveSupport::Concern
|
|
||||||
|
|
||||||
included do
|
|
||||||
embeds_many :category_items, :class_name => 'CustomFields::Types::Category::Item'
|
|
||||||
|
|
||||||
validates_associated :category_items
|
|
||||||
|
|
||||||
accepts_nested_attributes_for :category_items, :allow_destroy => true
|
|
||||||
|
|
||||||
register_type :category, ::String
|
|
||||||
end
|
|
||||||
|
|
||||||
module InstanceMethods
|
|
||||||
|
|
||||||
def ordered_category_items
|
|
||||||
self.category_items.sort { |a, b| (a.position || 0) <=> (b.position || 0) }
|
|
||||||
end
|
|
||||||
|
|
||||||
def category_names
|
|
||||||
self.category_items.collect(&:name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def category_ids
|
|
||||||
self.category_items.collect(&:_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def apply_category_type(klass)
|
|
||||||
klass.cattr_accessor :"#{self.safe_alias}_items"
|
|
||||||
|
|
||||||
klass.send("#{self.safe_alias}_items=", self.ordered_category_items)
|
|
||||||
|
|
||||||
klass.class_eval <<-EOF
|
|
||||||
def self.#{self.safe_alias}_names
|
|
||||||
self.#{self.safe_alias}_items.collect(&:name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.group_by_#{self.safe_alias}(list_method = nil)
|
|
||||||
groups = (if self.embedded?
|
|
||||||
list_method ||= self.association_name
|
|
||||||
self._parent.send(list_method)
|
|
||||||
else
|
|
||||||
list_method ||= :all
|
|
||||||
self.send(list_method)
|
|
||||||
end).to_a.group_by(&:#{self._name})
|
|
||||||
|
|
||||||
self.#{self.safe_alias}_items.collect do |category|
|
|
||||||
{
|
|
||||||
:name => category.name,
|
|
||||||
:items => groups[category._id] || []
|
|
||||||
}.with_indifferent_access
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def #{self.safe_alias}=(name)
|
|
||||||
category_id = self.class.#{self.safe_alias}_items.find { |item| item.name == name }._id rescue name
|
|
||||||
write_attribute(:#{self._name}, category_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def #{self.safe_alias}
|
|
||||||
category_id = read_attribute(:#{self._name})
|
|
||||||
self.class.#{self.safe_alias}_items.find { |item| item._id == category_id }.name rescue category_id
|
|
||||||
end
|
|
||||||
EOF
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class Item
|
|
||||||
|
|
||||||
include Mongoid::Document
|
|
||||||
|
|
||||||
field :name
|
|
||||||
field :position, :type => Integer, :default => 0
|
|
||||||
|
|
||||||
embedded_in :custom_field, :inverse_of => :category_items
|
|
||||||
|
|
||||||
validates_presence_of :name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,35 +0,0 @@
|
|||||||
module CustomFields
|
|
||||||
module Types
|
|
||||||
module Date
|
|
||||||
|
|
||||||
extend ActiveSupport::Concern
|
|
||||||
|
|
||||||
included do
|
|
||||||
register_type :date, ::Date
|
|
||||||
end
|
|
||||||
|
|
||||||
module InstanceMethods
|
|
||||||
|
|
||||||
def apply_date_type(klass)
|
|
||||||
|
|
||||||
klass.class_eval <<-EOF
|
|
||||||
def #{self.safe_alias}
|
|
||||||
self.#{self._name}.strftime(I18n.t('date.formats.default')) rescue nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def #{self.safe_alias}=(value)
|
|
||||||
if value.is_a?(String)
|
|
||||||
date = ::Date._strptime(value, I18n.t('date.formats.default'))
|
|
||||||
value = Date.new(date[:year], date[:mon], date[:mday])
|
|
||||||
end
|
|
||||||
self.#{self._name} = value
|
|
||||||
end
|
|
||||||
EOF
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,37 +0,0 @@
|
|||||||
module CustomFields
|
|
||||||
module Types
|
|
||||||
module Default
|
|
||||||
extend ActiveSupport::Concern
|
|
||||||
|
|
||||||
included do
|
|
||||||
cattr_accessor :field_types
|
|
||||||
end
|
|
||||||
|
|
||||||
module InstanceMethods
|
|
||||||
|
|
||||||
def apply_default_type(klass)
|
|
||||||
klass.class_eval <<-EOF
|
|
||||||
alias :#{self.safe_alias} :#{self._name}
|
|
||||||
alias :#{self.safe_alias}= :#{self._name}=
|
|
||||||
EOF
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
module ClassMethods
|
|
||||||
|
|
||||||
def register_type(kind, klass = ::String)
|
|
||||||
self.field_types ||= {}
|
|
||||||
self.field_types[kind.to_sym] = klass unless klass.nil?
|
|
||||||
|
|
||||||
self.class_eval <<-EOF
|
|
||||||
def #{kind.to_s}?
|
|
||||||
self.kind.downcase == '#{kind}' rescue false
|
|
||||||
end
|
|
||||||
EOF
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,27 +0,0 @@
|
|||||||
module CustomFields
|
|
||||||
module Types
|
|
||||||
module File
|
|
||||||
|
|
||||||
extend ActiveSupport::Concern
|
|
||||||
|
|
||||||
included do
|
|
||||||
register_type :file, nil # do not create the default field
|
|
||||||
end
|
|
||||||
|
|
||||||
module InstanceMethods
|
|
||||||
|
|
||||||
def apply_file_type(klass)
|
|
||||||
|
|
||||||
klass.mount_uploader self._name, FileUploader
|
|
||||||
|
|
||||||
self.apply_default_type(klass)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class FileUploader < ::CarrierWave::Uploader::Base
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,13 +0,0 @@
|
|||||||
module CustomFields
|
|
||||||
module Types
|
|
||||||
module String
|
|
||||||
|
|
||||||
extend ActiveSupport::Concern
|
|
||||||
|
|
||||||
included do
|
|
||||||
register_type :string
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,15 +0,0 @@
|
|||||||
module CustomFields
|
|
||||||
module Types
|
|
||||||
module Text
|
|
||||||
|
|
||||||
extend ActiveSupport::Concern
|
|
||||||
|
|
||||||
included do
|
|
||||||
field :text_formatting, :default => 'html'
|
|
||||||
|
|
||||||
register_type :text
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1 +0,0 @@
|
|||||||
Hello world !
|
|
@ -1,28 +0,0 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe CustomFields::CustomFieldsFor do
|
|
||||||
|
|
||||||
describe 'Saving' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@project = Project.new(:name => 'Locomotive')
|
|
||||||
@project.person_custom_fields.build(:label => 'E-mail', :_alias => 'email', :kind => 'String')
|
|
||||||
@project.person_custom_fields.build(:label => 'Age', :_alias => 'age', :kind => 'String')
|
|
||||||
end
|
|
||||||
|
|
||||||
context '@create' do
|
|
||||||
|
|
||||||
it 'persists parent object' do
|
|
||||||
lambda { @project.save }.should change(Project, :count).by(1)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'persists custom fields' do
|
|
||||||
@project.save && @project.reload
|
|
||||||
@project.person_custom_fields.count.should == 2
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
@ -1,26 +0,0 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe CustomFields::Types::Category do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@project = Project.new(:name => 'Locomotive')
|
|
||||||
@field = @project.task_custom_fields.build(:label => 'Main category', :_alias => 'main_category', :kind => 'Category')
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'saving category items' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@field.category_items.build :name => 'Development'
|
|
||||||
@field.category_items.build :name => 'Design'
|
|
||||||
@field.updated_at = Time.now
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'persists items' do
|
|
||||||
@field.save.should be_true
|
|
||||||
@project.reload
|
|
||||||
@project.task_custom_fields.first.category_items.size.should == 2
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
@ -1,18 +0,0 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe CustomFields::Types::File do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@project = Project.new(:name => 'Locomotive')
|
|
||||||
@project.task_custom_fields.build(:label => 'Screenshot', :_alias => 'screenshot', :kind => 'File')
|
|
||||||
@project.save
|
|
||||||
@task = @project.tasks.build
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'attaches file' do
|
|
||||||
@task.screenshot = FixturedFile.open('doc.txt')
|
|
||||||
@task.save
|
|
||||||
@task.screenshot.url.should == '/uploads/doc.txt'
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
@ -1,10 +0,0 @@
|
|||||||
class Person
|
|
||||||
|
|
||||||
include Mongoid::Document
|
|
||||||
include CustomFields::ProxyClassEnabler
|
|
||||||
|
|
||||||
field :full_name
|
|
||||||
|
|
||||||
embedded_in :project, :inverse_of => :people
|
|
||||||
|
|
||||||
end
|
|
@ -1,18 +0,0 @@
|
|||||||
class Project
|
|
||||||
|
|
||||||
include Mongoid::Document
|
|
||||||
include CustomFields::ProxyClassEnabler
|
|
||||||
include CustomFields::CustomFieldsFor
|
|
||||||
|
|
||||||
field :name
|
|
||||||
field :description
|
|
||||||
|
|
||||||
references_many :people
|
|
||||||
embeds_many :tasks
|
|
||||||
|
|
||||||
custom_fields_for :people
|
|
||||||
custom_fields_for :tasks
|
|
||||||
|
|
||||||
scope :ordered, :order_by => [[:name, :asc]]
|
|
||||||
|
|
||||||
end
|
|
10
vendor/plugins/custom_fields/spec/models/task.rb
vendored
10
vendor/plugins/custom_fields/spec/models/task.rb
vendored
@ -1,10 +0,0 @@
|
|||||||
class Task
|
|
||||||
|
|
||||||
include Mongoid::Document
|
|
||||||
include CustomFields::ProxyClassEnabler
|
|
||||||
|
|
||||||
field :title
|
|
||||||
|
|
||||||
embedded_in :project, :inverse_of => :tasks
|
|
||||||
|
|
||||||
end
|
|
27
vendor/plugins/custom_fields/spec/spec_helper.rb
vendored
27
vendor/plugins/custom_fields/spec/spec_helper.rb
vendored
@ -1,27 +0,0 @@
|
|||||||
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
||||||
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
|
|
||||||
|
|
||||||
MODELS = File.join(File.dirname(__FILE__), 'models')
|
|
||||||
$LOAD_PATH.unshift(MODELS)
|
|
||||||
|
|
||||||
require 'rubygems'
|
|
||||||
require 'bundler'
|
|
||||||
Bundler.setup
|
|
||||||
Bundler.require
|
|
||||||
|
|
||||||
require 'mongoid'
|
|
||||||
require 'mocha'
|
|
||||||
require 'rspec'
|
|
||||||
require 'custom_fields'
|
|
||||||
|
|
||||||
Dir[ File.join(MODELS, "*.rb") ].sort.each { |file| require File.basename(file) }
|
|
||||||
|
|
||||||
require 'support/mongoid'
|
|
||||||
require 'support/carrierwave'
|
|
||||||
|
|
||||||
Rspec.configure do |config|
|
|
||||||
config.mock_with :mocha
|
|
||||||
config.after :suite do
|
|
||||||
Mongoid.master.collections.select { |c| c.name != 'system.indexes' }.each(&:drop)
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,31 +0,0 @@
|
|||||||
require 'carrierwave/test/matchers'
|
|
||||||
|
|
||||||
CarrierWave.configure do |config|
|
|
||||||
config.storage = :file
|
|
||||||
config.store_dir = "uploads"
|
|
||||||
config.cache_dir = "cache"
|
|
||||||
config.root = File.join(File.dirname(__FILE__), '..', 'tmp')
|
|
||||||
end
|
|
||||||
|
|
||||||
module FixturedFile
|
|
||||||
def self.open(filename)
|
|
||||||
File.new(self.path(filename))
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.path(filename)
|
|
||||||
File.join(File.dirname(__FILE__), '..', 'fixtures', filename)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.duplicate(filename)
|
|
||||||
dst = File.join(File.dirname(__FILE__), '..', 'tmp', filename)
|
|
||||||
FileUtils.cp self.path(filename), dst
|
|
||||||
dst
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.reset!
|
|
||||||
FileUtils.rm_rf(File.join(File.dirname(__FILE__), '..', 'tmp'))
|
|
||||||
FileUtils.mkdir(File.join(File.dirname(__FILE__), '..', 'tmp'))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
FixturedFile.reset!
|
|
@ -1,6 +0,0 @@
|
|||||||
Mongoid.configure do |config|
|
|
||||||
name = "custom_fields_test"
|
|
||||||
host = "localhost"
|
|
||||||
config.master = Mongo::Connection.new.db(name)
|
|
||||||
# config.master = Mongo::Connection.new('localhost', '27017', :logger => Logger.new($stdout)).db(name)
|
|
||||||
end
|
|
@ -1,42 +0,0 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe CustomFields::Field do
|
|
||||||
|
|
||||||
it 'is initialized' do
|
|
||||||
lambda { CustomFields::Field.new }.should_not raise_error
|
|
||||||
end
|
|
||||||
|
|
||||||
context '#mongoid' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@field = CustomFields::Field.new(:label => 'manager', :_name => 'field_1', :kind => 'String', :_alias => 'manager')
|
|
||||||
@field.stubs(:valid?).returns(true)
|
|
||||||
@project = Project.to_klass_with_custom_fields(@field).new
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'is added to the list of mongoid fields' do
|
|
||||||
@project.fields['field_1'].should_not be_nil
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'on target class' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@field = CustomFields::Field.new(:label => 'manager', :_name => 'field_1', :kind => 'String', :_alias => 'manager')
|
|
||||||
@field.stubs(:valid?).returns(true)
|
|
||||||
@project = Project.to_klass_with_custom_fields(@field).new
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'has a new field' do
|
|
||||||
@project.respond_to?(:manager).should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'sets / retrieves a value' do
|
|
||||||
@project.manager = 'Mickael Scott'
|
|
||||||
@project.manager.should == 'Mickael Scott'
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
@ -1,106 +0,0 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe CustomFields::CustomFieldsFor do
|
|
||||||
|
|
||||||
context '#proxy class' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@project = Project.new
|
|
||||||
@klass = @project.tasks.klass
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns the proxy class in the association' do
|
|
||||||
@klass.should == @project.tasks.build.class
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'has a link to the parent' do
|
|
||||||
@klass._parent.should == @project
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'has the association name which references to' do
|
|
||||||
@klass.association_name.should == 'tasks'
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with embedded collection' do
|
|
||||||
|
|
||||||
context '#association' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@project = Project.new
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'has custom fields for embedded collection' do
|
|
||||||
@project.respond_to?(:task_custom_fields).should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
context '#building' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@project = Project.new
|
|
||||||
@project.task_custom_fields.build :label => 'Short summary', :_alias => 'summary', :kind => 'String'
|
|
||||||
@task = @project.tasks.build
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns a new document whose Class is different from the original one' do
|
|
||||||
@task.class.should_not == Task
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns a new document with custom field' do
|
|
||||||
@project.tasks.build
|
|
||||||
@project.tasks.build
|
|
||||||
@task.respond_to?(:summary).should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'sets/gets custom attributes' do
|
|
||||||
@task.summary = 'Lorem ipsum...'
|
|
||||||
@task.summary.should == 'Lorem ipsum...'
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with related collection' do
|
|
||||||
|
|
||||||
context '#association' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@project = Project.new
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'has custom fields for related collections' do
|
|
||||||
@project.respond_to?(:person_custom_fields).should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
context '#building' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@project = Project.new
|
|
||||||
@project.person_custom_fields.build :label => 'Position in the project', :_alias => 'position', :kind => 'String'
|
|
||||||
@person = @project.people.build
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns a new document whose Class is different from the original one' do
|
|
||||||
@person.class.should_not == Person
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns a new document with custom field' do
|
|
||||||
@person.respond_to?(:position).should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'sets/gets custom attributes' do
|
|
||||||
@person.position = 'Designer'
|
|
||||||
@person.position.should == 'Designer'
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
@ -1,25 +0,0 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe CustomFields::ProxyClassEnabler do
|
|
||||||
|
|
||||||
context '#proxy klass' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@klass = Task.to_klass_with_custom_fields([])
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'does not be flagged as a inherited document' do
|
|
||||||
@klass.new.hereditary?.should be_false
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'has a list of custom fields' do
|
|
||||||
@klass.custom_fields.should == []
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'has the exact same model name than its parent' do
|
|
||||||
@klass.model_name.should == 'Task'
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
@ -1,81 +0,0 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe CustomFields::Types::Boolean do
|
|
||||||
|
|
||||||
context 'on field class' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@field = CustomFields::Field.new
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns true if it is a Boolean' do
|
|
||||||
@field.kind = 'boolean'
|
|
||||||
@field.boolean?.should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns false if it is not a Boolean' do
|
|
||||||
@field.kind = 'string'
|
|
||||||
@field.boolean?.should be_false
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'on target class' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@project = build_project_with_boolean
|
|
||||||
end
|
|
||||||
|
|
||||||
context '#setting' do
|
|
||||||
|
|
||||||
context '#true' do
|
|
||||||
|
|
||||||
it 'sets value from an integer' do
|
|
||||||
@project.active = 1
|
|
||||||
@project.active.should == true
|
|
||||||
@project.field_1.should == '1'
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'sets value from a string' do
|
|
||||||
@project.active = '1'
|
|
||||||
@project.active.should == true
|
|
||||||
@project.field_1.should == '1'
|
|
||||||
|
|
||||||
@project.active = 'true'
|
|
||||||
@project.active.should == true
|
|
||||||
@project.field_1.should == 'true'
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
context '#false' do
|
|
||||||
|
|
||||||
it 'sets value from an integer' do
|
|
||||||
@project.active = 0
|
|
||||||
@project.active.should == false
|
|
||||||
@project.field_1.should == '0'
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'sets value from a string' do
|
|
||||||
@project.active = '0'
|
|
||||||
@project.active.should == false
|
|
||||||
@project.field_1.should == '0'
|
|
||||||
|
|
||||||
@project.active = 'false'
|
|
||||||
@project.active.should == false
|
|
||||||
@project.field_1.should == 'false'
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_project_with_boolean
|
|
||||||
field = CustomFields::Field.new(:label => 'Active', :_name => 'field_1', :kind => 'Boolean')
|
|
||||||
field.stubs(:valid?).returns(true)
|
|
||||||
Project.to_klass_with_custom_fields(field).new
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
@ -1,112 +0,0 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe CustomFields::Types::Category do
|
|
||||||
|
|
||||||
context 'on field class' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@field = CustomFields::Field.new
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'has the category items field' do
|
|
||||||
@field.respond_to?(:category_items).should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'has the apply method used for the target object' do
|
|
||||||
@field.respond_to?(:apply_category_type).should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns true if it is a Category' do
|
|
||||||
@field.kind = 'category'
|
|
||||||
@field.category?.should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns false if it is not a Category' do
|
|
||||||
@field.kind = 'string'
|
|
||||||
@field.category?.should be_false
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'on target class' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@project = build_project_with_category
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'has getter/setter' do
|
|
||||||
@project.respond_to?(:global_category).should be_true
|
|
||||||
@project.respond_to?(:global_category=).should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'has the values of this category' do
|
|
||||||
@project.class.global_category_names.should == %w{Maintenance Design Development}
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'sets the category from a name' do
|
|
||||||
@project.global_category = 'Design'
|
|
||||||
@project.global_category.should == 'Design'
|
|
||||||
@project.field_1.should == '42'
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'sets the category even it does not exit' do
|
|
||||||
@project.global_category = 'Accounting'
|
|
||||||
@project.global_category.should == 'Accounting'
|
|
||||||
@project.field_1.should == 'Accounting'
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'group by category' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
seed_projects
|
|
||||||
@groups = @project.class.group_by_global_category
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'is an non empty array' do
|
|
||||||
@groups.class.should == Array
|
|
||||||
@groups.size.should == 3
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'is an array of hash composed of a name' do
|
|
||||||
@groups.collect { |g| g[:name] }.should == %w{Maintenance Design Development}
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'is an array of hash composed of a list of objects' do
|
|
||||||
@groups[0][:items].size.should == 0
|
|
||||||
@groups[1][:items].size.should == 1
|
|
||||||
@groups[2][:items].size.should == 2
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'passes method to retrieve items' do
|
|
||||||
@project.class.expects(:ordered)
|
|
||||||
@project.class.group_by_global_category(:ordered)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_project_with_category
|
|
||||||
field = build_category
|
|
||||||
Project.to_klass_with_custom_fields(field).new
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_category
|
|
||||||
field = CustomFields::Field.new(:label => 'global_category', :_name => 'field_1', :kind => 'Category')
|
|
||||||
field.stubs(:valid?).returns(true)
|
|
||||||
field.category_items.build :name => 'Development', :_id => '41', :position => 2
|
|
||||||
field.category_items.build :name => 'Design', :_id => '42', :position => 1
|
|
||||||
field.category_items.build :name => 'Maintenance', :_id => '43', :position => 0
|
|
||||||
field
|
|
||||||
end
|
|
||||||
|
|
||||||
def seed_projects
|
|
||||||
list = [
|
|
||||||
@project.class.new(:name => 'Locomotive CMS', :global_category => '41'),
|
|
||||||
@project.class.new(:name => 'Ruby on Rails', :global_category => '41'),
|
|
||||||
@project.class.new(:name => 'Dribble', :global_category => '42')
|
|
||||||
]
|
|
||||||
@project.class.stubs(:all).returns(list)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
@ -1,59 +0,0 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe CustomFields::Types::Date do
|
|
||||||
|
|
||||||
context 'on field class' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@field = CustomFields::Field.new
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns true if it is a Date' do
|
|
||||||
@field.kind = 'Date'
|
|
||||||
@field.date?.should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns false if it is not a Date' do
|
|
||||||
@field.kind = 'string'
|
|
||||||
@field.date?.should be_false
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'on target class' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@project = build_project_with_date
|
|
||||||
@date = Date.parse('2010-06-29')
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'sets value from a date' do
|
|
||||||
@project.started_at = @date
|
|
||||||
@project.started_at.should == '2010-06-29'
|
|
||||||
@project.field_1.class.should == Date
|
|
||||||
@project.field_1.should == @date
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'sets value from a string' do
|
|
||||||
@project.started_at = '2010-06-29'
|
|
||||||
@project.started_at.class.should == String
|
|
||||||
@project.started_at.should == '2010-06-29'
|
|
||||||
@project.field_1.class.should == Date
|
|
||||||
@project.field_1.should == @date
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'sets nil value' do
|
|
||||||
@project.started_at = nil
|
|
||||||
@project.started_at.should be_nil
|
|
||||||
@project.field_1.should be_nil
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_project_with_date
|
|
||||||
field = CustomFields::Field.new(:label => 'Started at', :_name => 'field_1', :kind => 'Date')
|
|
||||||
field.stubs(:valid?).returns(true)
|
|
||||||
Project.to_klass_with_custom_fields(field).new
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
@ -1,23 +0,0 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe CustomFields::Types::Date do
|
|
||||||
|
|
||||||
context 'on field class' do
|
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@field = CustomFields::Field.new
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns true if it is a Date' do
|
|
||||||
@field.kind = 'File'
|
|
||||||
@field.file?.should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns false if it is not a Date' do
|
|
||||||
@field.kind = 'string'
|
|
||||||
@field.file?.should be_false
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
1
vendor/plugins/custom_fields/uninstall.rb
vendored
1
vendor/plugins/custom_fields/uninstall.rb
vendored
@ -1 +0,0 @@
|
|||||||
# Uninstall hook code here
|
|
Loading…
Reference in New Issue
Block a user