comfortable_mexican_sofa 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +83 -1
- data/VERSION +1 -1
- data/app/controllers/cms_admin/base_controller.rb +15 -0
- data/app/controllers/cms_admin/layouts_controller.rb +3 -3
- data/app/controllers/cms_admin/pages_controller.rb +8 -8
- data/app/controllers/cms_admin/sites_controller.rb +58 -0
- data/app/controllers/cms_admin/snippets_controller.rb +18 -14
- data/app/controllers/cms_admin/uploads_controller.rb +7 -5
- data/app/controllers/cms_content_controller.rb +17 -5
- data/app/models/cms_layout.rb +7 -7
- data/app/models/cms_page.rb +18 -4
- data/app/models/cms_site.rb +23 -0
- data/app/models/cms_snippet.rb +17 -12
- data/app/models/cms_upload.rb +4 -7
- data/app/views/cms_admin/layouts/_form.html.erb +1 -1
- data/app/views/cms_admin/layouts/index.html.erb +1 -1
- data/app/views/cms_admin/pages/_form.html.erb +3 -2
- data/app/views/cms_admin/pages/_form_blocks.html.erb +1 -1
- data/app/views/cms_admin/pages/_index_branch.html.erb +1 -1
- data/app/views/cms_admin/pages/index.html.erb +1 -1
- data/app/views/cms_admin/sites/_form.html.erb +2 -0
- data/app/views/cms_admin/sites/edit.html.erb +6 -0
- data/app/views/cms_admin/sites/index.html.erb +22 -0
- data/app/views/cms_admin/sites/new.html.erb +6 -0
- data/app/views/cms_admin/snippets/_form.html.erb +2 -1
- data/app/views/cms_admin/snippets/index.html.erb +20 -1
- data/app/views/layouts/cms_admin.html.erb +2 -1
- data/comfortable_mexican_sofa.gemspec +31 -9
- data/config/initializers/comfortable_mexican_sofa.rb +10 -0
- data/config/routes.rb +3 -1
- data/db/migrate/01_create_cms.rb +18 -4
- data/lib/comfortable_mexican_sofa.rb +28 -22
- data/lib/comfortable_mexican_sofa/acts_as_tree.rb +97 -0
- data/lib/comfortable_mexican_sofa/cms_tag/snippet.rb +4 -0
- data/lib/comfortable_mexican_sofa/configuration.rb +19 -0
- data/lib/comfortable_mexican_sofa/controller_methods.rb +41 -0
- data/lib/comfortable_mexican_sofa/{cms_engine.rb → engine.rb} +1 -1
- data/lib/comfortable_mexican_sofa/{cms_form_builder.rb → form_builder.rb} +1 -1
- data/lib/comfortable_mexican_sofa/http_auth.rb +17 -0
- data/lib/comfortable_mexican_sofa/rails_extensions.rb +11 -0
- data/lib/comfortable_mexican_sofa/view_methods.rb +33 -0
- data/lib/generators/cms_generator.rb +4 -0
- data/public/stylesheets/comfortable_mexican_sofa/structure.css +10 -12
- data/test/fixtures/cms_layouts.yml +3 -1
- data/test/fixtures/cms_pages.yml +6 -2
- data/test/fixtures/cms_sites.yml +3 -0
- data/test/fixtures/cms_snippets.yml +3 -1
- data/test/fixtures/cms_uploads.yml +1 -0
- data/test/functional/cms_admin/layouts_controller_test.rb +3 -1
- data/test/functional/cms_admin/pages_controller_test.rb +4 -2
- data/test/functional/cms_admin/sites_controller_test.rb +92 -0
- data/test/functional/cms_admin/snippets_controller_test.rb +62 -37
- data/test/functional/cms_content_controller_test.rb +32 -5
- data/test/integration/authentication_test.rb +27 -0
- data/test/integration/render_cms_test.rb +57 -0
- data/test/integration/sites_test.rb +30 -0
- data/test/test_helper.rb +46 -3
- data/test/unit/cms_block_test.rb +1 -0
- data/test/unit/cms_configuration_test.rb +16 -0
- data/test/unit/cms_layout_test.rb +3 -3
- data/test/unit/cms_page_test.rb +23 -13
- data/test/unit/cms_site_test.rb +41 -0
- data/test/unit/cms_snippet_test.rb +1 -1
- data/test/unit/cms_tags/snippet_test.rb +1 -1
- data/test/unit/cms_upload_test.rb +7 -6
- metadata +32 -10
- data/lib/comfortable_mexican_sofa/cms_acts_as_tree.rb +0 -101
- data/lib/comfortable_mexican_sofa/cms_rails_extensions.rb +0 -32
- data/test/functional/cms_admin/base_controller_test.rb +0 -9
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,86 @@
|
|
1
1
|
Comfortable Mexican Sofa (CMS)
|
2
2
|
==============================
|
3
3
|
|
4
|
-
|
4
|
+
What is this?
|
5
|
+
-------------
|
6
|
+
Comfortable Mexican Sofa is a Content Management System with an obnoxious name. Also it's a Rails 3 Engine. This means that you can use it as a stand-alone application and also as an Engine for your existing application.
|
7
|
+
|
8
|
+
Installation
|
9
|
+
------------
|
10
|
+
|
11
|
+
### Stand-alone
|
12
|
+
TODO: Need to create some sort of setup, so you can simply run:
|
13
|
+
|
14
|
+
$ comfortable_mexican_sofa my_new_app
|
15
|
+
|
16
|
+
### As a Rails Engine
|
17
|
+
Add gem definition to your Gemfile:
|
18
|
+
|
19
|
+
config.gem 'comfortable_mexican_sofa'
|
20
|
+
|
21
|
+
Then from the Rails project's root run:
|
22
|
+
|
23
|
+
bundle install
|
24
|
+
rails g cms
|
25
|
+
rake db:migrate
|
26
|
+
|
27
|
+
At this point you should have database structure created, some assets copied to /public directory and initializer set up:
|
28
|
+
|
29
|
+
ComfortableMexicanSofa.configure do |config|
|
30
|
+
config.cms_title = 'ComfortableMexicanSofa'
|
31
|
+
config.authentication = 'ComfortableMexicanSofa::HttpAuth'
|
32
|
+
end
|
33
|
+
|
34
|
+
# Credentials for CmsHttpAuthentication
|
35
|
+
ComfortableMexicanSofa::HttpAuth.username = 'username'
|
36
|
+
ComfortableMexicanSofa::HttpAuth.password = 'password'
|
37
|
+
|
38
|
+
Usage
|
39
|
+
-----
|
40
|
+
|
41
|
+
Now you should be able to navigate to http://yoursite/cms-admin
|
42
|
+
|
43
|
+
### Step 1: Create Site
|
44
|
+
CMS allows you to run multiple sites from a single installation. Each site is attached to a hostname. For the first time you'll be prompted to set up the initial site. Hostname will be pre-populated so just choose a label.
|
45
|
+
|
46
|
+
### Step 2: Create Layout
|
47
|
+
Before creating pages and populating them with content we need to create a layout. Layout is the template of your pages. It defines some reusable content (like header and footer, for example) and places where the content goes. A very simple layout can look like this:
|
48
|
+
|
49
|
+
<html>
|
50
|
+
<body>
|
51
|
+
<h1>My Awesome Site</h1>
|
52
|
+
<cms:page:content>
|
53
|
+
</body>
|
54
|
+
</html>
|
55
|
+
|
56
|
+
So there's your layout and the `<cms:page:content>` defines a place where renderable `content` will go. There's just a handful of tags that you can use.
|
57
|
+
|
58
|
+
*Page Blocks* are pieces of content that will be output on the page:
|
59
|
+
|
60
|
+
<cms:page:some_label:text> # same as <cms:page:some_label>, will render a text area during page creation
|
61
|
+
<cms:page:some_label:string> # will render a text field during page creation
|
62
|
+
<cms:page:some_label:datetime> # datetime select widget
|
63
|
+
<cms:page:some_label:integer> # a number field
|
64
|
+
|
65
|
+
*Page Fields* are pieces of content that are not rendered. They are useful for hidden values you want to use inside your app.
|
66
|
+
|
67
|
+
<cms:field:some_label:text> # text area for the page creation form
|
68
|
+
<cms:field:some_label:string> # same as <cms:field:some_label>, this is a text field
|
69
|
+
<cms:field:some_label:datetime> # datetime
|
70
|
+
<cms:field:some_label:integer> # a number field
|
71
|
+
|
72
|
+
*Snippets* bits of reusable content that can be used in pages and layouts
|
73
|
+
|
74
|
+
<cms:snippet:snippet_slug>
|
75
|
+
|
76
|
+
*Partials* are exactly that. You don't want to do IRB inside CMS so there's a handy tag:
|
77
|
+
|
78
|
+
<cms:partial:path/to/partial>
|
79
|
+
|
80
|
+
You don't have to define entire html layout, however. You can simply re-use your application one. Page content will be yielded into it like any normal view.
|
81
|
+
|
82
|
+
TODO: more stuff
|
83
|
+
|
84
|
+
### Step 3: Create Page
|
85
|
+
|
86
|
+
TODO: You pres butan page is created. Yay!
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.2
|
@@ -1,5 +1,20 @@
|
|
1
|
+
# Authentication module must have #authenticate method
|
2
|
+
include ComfortableMexicanSofa.config.authentication.to_s.constantize
|
3
|
+
|
1
4
|
class CmsAdmin::BaseController < ApplicationController
|
2
5
|
|
6
|
+
before_filter :authenticate,
|
7
|
+
:load_admin_cms_site
|
8
|
+
|
3
9
|
layout 'cms_admin'
|
10
|
+
|
11
|
+
protected
|
4
12
|
|
13
|
+
def load_admin_cms_site
|
14
|
+
@cms_site = CmsSite.find_by_hostname!(request.host.downcase)
|
15
|
+
rescue ActiveRecord::RecordNotFound
|
16
|
+
flash[:error] = 'No Site defined for this hostname. Create it now.'
|
17
|
+
redirect_to new_cms_admin_site_path
|
18
|
+
end
|
19
|
+
|
5
20
|
end
|
@@ -4,7 +4,7 @@ class CmsAdmin::LayoutsController < CmsAdmin::BaseController
|
|
4
4
|
before_filter :load_cms_layout, :only => [:edit, :update, :destroy]
|
5
5
|
|
6
6
|
def index
|
7
|
-
@cms_layouts =
|
7
|
+
@cms_layouts = @cms_site.cms_layouts.roots
|
8
8
|
end
|
9
9
|
|
10
10
|
def new
|
@@ -42,12 +42,12 @@ class CmsAdmin::LayoutsController < CmsAdmin::BaseController
|
|
42
42
|
protected
|
43
43
|
|
44
44
|
def build_cms_layout
|
45
|
-
@cms_layout =
|
45
|
+
@cms_layout = @cms_site.cms_layouts.new(params[:cms_layout])
|
46
46
|
@cms_layout.parent ||= CmsLayout.find_by_id(params[:parent_id])
|
47
47
|
end
|
48
48
|
|
49
49
|
def load_cms_layout
|
50
|
-
@cms_layout =
|
50
|
+
@cms_layout = @cms_site.cms_layouts.find(params[:id])
|
51
51
|
rescue ActiveRecord::RecordNotFound
|
52
52
|
flash[:error] = 'Layout not found'
|
53
53
|
redirect_to :action => :index
|
@@ -4,7 +4,7 @@ class CmsAdmin::PagesController < CmsAdmin::BaseController
|
|
4
4
|
before_filter :load_cms_page, :only => [:edit, :update, :destroy]
|
5
5
|
|
6
6
|
def index
|
7
|
-
@cms_pages = [
|
7
|
+
@cms_pages = [@cms_site.cms_pages.root].compact
|
8
8
|
end
|
9
9
|
|
10
10
|
def new
|
@@ -40,21 +40,21 @@ class CmsAdmin::PagesController < CmsAdmin::BaseController
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def form_blocks
|
43
|
-
@cms_page =
|
44
|
-
@cms_page.cms_layout =
|
43
|
+
@cms_page = @cms_site.cms_pages.find_by_id(params[:id]) || CmsPage.new
|
44
|
+
@cms_page.cms_layout = @cms_site.cms_layouts.find_by_id(params[:layout_id])
|
45
45
|
end
|
46
46
|
|
47
47
|
protected
|
48
48
|
|
49
49
|
def build_cms_page
|
50
|
-
@cms_page =
|
51
|
-
@cms_page.parent ||= (CmsPage.find_by_id(params[:parent_id]) ||
|
52
|
-
@cms_page.cms_layout ||= (@cms_page.parent && @cms_page.parent.cms_layout ||
|
50
|
+
@cms_page = @cms_site.cms_pages.new(params[:cms_page])
|
51
|
+
@cms_page.parent ||= (CmsPage.find_by_id(params[:parent_id]) || @cms_site.cms_pages.root)
|
52
|
+
@cms_page.cms_layout ||= (@cms_page.parent && @cms_page.parent.cms_layout || @cms_site.cms_layouts.first)
|
53
53
|
end
|
54
54
|
|
55
55
|
def load_cms_page
|
56
|
-
@cms_page =
|
57
|
-
@cms_page.cms_layout ||= (@cms_page.parent && @cms_page.parent.cms_layout ||
|
56
|
+
@cms_page = @cms_site.cms_pages.find(params[:id])
|
57
|
+
@cms_page.cms_layout ||= (@cms_page.parent && @cms_page.parent.cms_layout || @cms_site.cms_layouts.first)
|
58
58
|
rescue ActiveRecord::RecordNotFound
|
59
59
|
flash[:error] = 'Page not found'
|
60
60
|
redirect_to :action => :index
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class CmsAdmin::SitesController < CmsAdmin::BaseController
|
2
|
+
|
3
|
+
skip_before_filter :load_admin_cms_site
|
4
|
+
|
5
|
+
before_filter :build_cms_site, :only => [:new, :create]
|
6
|
+
before_filter :load_cms_site, :only => [:edit, :update, :destroy]
|
7
|
+
|
8
|
+
def index
|
9
|
+
@cms_sites = CmsSite.all
|
10
|
+
end
|
11
|
+
|
12
|
+
def new
|
13
|
+
render
|
14
|
+
end
|
15
|
+
|
16
|
+
def edit
|
17
|
+
render
|
18
|
+
end
|
19
|
+
|
20
|
+
def create
|
21
|
+
@cms_site.save!
|
22
|
+
flash[:notice] = 'Site created'
|
23
|
+
redirect_to :action => :edit, :id => @cms_site
|
24
|
+
rescue ActiveRecord::RecordInvalid
|
25
|
+
flash.now[:error] = 'Failed to create site'
|
26
|
+
render :action => :new
|
27
|
+
end
|
28
|
+
|
29
|
+
def update
|
30
|
+
@cms_site.update_attributes!(params[:cms_site])
|
31
|
+
flash[:notice] = 'Site updated'
|
32
|
+
redirect_to :action => :edit, :id => @cms_site
|
33
|
+
rescue ActiveRecord::RecordInvalid
|
34
|
+
flash.now[:error] = 'Failed to update site'
|
35
|
+
render :action => :edit
|
36
|
+
end
|
37
|
+
|
38
|
+
def destroy
|
39
|
+
@cms_site.destroy
|
40
|
+
flash[:notice] = 'Site deleted'
|
41
|
+
redirect_to :action => :index
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def build_cms_site
|
47
|
+
@cms_site = CmsSite.new(params[:cms_site])
|
48
|
+
@cms_site.hostname ||= request.host.downcase
|
49
|
+
end
|
50
|
+
|
51
|
+
def load_cms_site
|
52
|
+
@cms_site = CmsSite.find(params[:id])
|
53
|
+
rescue ActiveRecord::RecordNotFound
|
54
|
+
flash[:error] = 'Site not found'
|
55
|
+
redirect_to :action => :index
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -1,32 +1,35 @@
|
|
1
1
|
class CmsAdmin::SnippetsController < CmsAdmin::BaseController
|
2
|
-
|
3
|
-
|
4
|
-
before_filter :load_cms_snippet,
|
5
|
-
|
6
|
-
|
2
|
+
|
3
|
+
before_filter :build_cms_snippet, :only => [:new, :create]
|
4
|
+
before_filter :load_cms_snippet, :only => [:edit, :update, :destroy]
|
5
|
+
|
7
6
|
def index
|
8
|
-
@cms_snippets =
|
7
|
+
@cms_snippets = @cms_site.cms_snippets.all(:order => 'label')
|
9
8
|
end
|
10
9
|
|
11
10
|
def new
|
11
|
+
render
|
12
|
+
end
|
13
|
+
|
14
|
+
def edit
|
15
|
+
render
|
12
16
|
end
|
13
17
|
|
14
18
|
def create
|
15
19
|
@cms_snippet.save!
|
16
|
-
flash[:notice] = 'Snippet
|
20
|
+
flash[:notice] = 'Snippet created'
|
17
21
|
redirect_to :action => :edit, :id => @cms_snippet
|
18
22
|
rescue ActiveRecord::RecordInvalid
|
23
|
+
flash.now[:error] = 'Failed to create snippet'
|
19
24
|
render :action => :new
|
20
25
|
end
|
21
26
|
|
22
|
-
def edit
|
23
|
-
end
|
24
|
-
|
25
27
|
def update
|
26
28
|
@cms_snippet.update_attributes!(params[:cms_snippet])
|
27
|
-
flash[:notice] = 'Snippet
|
29
|
+
flash[:notice] = 'Snippet updated'
|
28
30
|
redirect_to :action => :edit, :id => @cms_snippet
|
29
31
|
rescue ActiveRecord::RecordInvalid
|
32
|
+
flash.now[:error] = 'Failed to update snippet'
|
30
33
|
render :action => :edit
|
31
34
|
end
|
32
35
|
|
@@ -35,14 +38,15 @@ class CmsAdmin::SnippetsController < CmsAdmin::BaseController
|
|
35
38
|
flash[:notice] = 'Snippet deleted'
|
36
39
|
redirect_to :action => :index
|
37
40
|
end
|
38
|
-
|
41
|
+
|
39
42
|
protected
|
43
|
+
|
40
44
|
def build_cms_snippet
|
41
|
-
@cms_snippet =
|
45
|
+
@cms_snippet = @cms_site.cms_snippets.new(params[:cms_snippet])
|
42
46
|
end
|
43
47
|
|
44
48
|
def load_cms_snippet
|
45
|
-
@cms_snippet =
|
49
|
+
@cms_snippet = @cms_site.cms_snippets.find(params[:id])
|
46
50
|
rescue ActiveRecord::RecordNotFound
|
47
51
|
flash[:error] = 'Snippet not found'
|
48
52
|
redirect_to :action => :index
|
@@ -1,12 +1,13 @@
|
|
1
1
|
class CmsAdmin::UploadsController < CmsAdmin::BaseController
|
2
|
-
|
3
|
-
|
2
|
+
|
3
|
+
before_filter :load_cms_upload, :only => :destroy
|
4
4
|
|
5
5
|
def index
|
6
|
+
render
|
6
7
|
end
|
7
8
|
|
8
9
|
def create
|
9
|
-
@cms_upload =
|
10
|
+
@cms_upload = @cms_site.cms_uploads.new(:uploaded_file => params[:file])
|
10
11
|
if @cms_upload.save
|
11
12
|
render(:partial => 'cms_admin/uploads/upload', :object => @cms_upload)
|
12
13
|
else
|
@@ -17,10 +18,11 @@ class CmsAdmin::UploadsController < CmsAdmin::BaseController
|
|
17
18
|
def destroy
|
18
19
|
@cms_upload.destroy
|
19
20
|
end
|
20
|
-
|
21
|
+
|
21
22
|
protected
|
23
|
+
|
22
24
|
def load_cms_upload
|
23
|
-
@cms_upload =
|
25
|
+
@cms_upload = @cms_site.cms_uploads.find(params[:id])
|
24
26
|
rescue ActiveRecord::RecordNotFound
|
25
27
|
render :nothing => true
|
26
28
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
class CmsContentController < ApplicationController
|
2
2
|
|
3
|
+
before_filter :load_cms_site
|
3
4
|
before_filter :load_cms_page, :only => :render_html
|
4
5
|
before_filter :load_cms_layout, :only => [:render_css, :render_js]
|
5
6
|
|
6
|
-
def render_html
|
7
|
+
def render_html(status = 200)
|
7
8
|
layout = @cms_page.cms_layout.app_layout.blank?? false : @cms_page.cms_layout.app_layout
|
8
|
-
render :inline => @cms_page.content, :layout => layout
|
9
|
+
render :inline => @cms_page.content, :layout => layout, :status => status
|
9
10
|
end
|
10
11
|
|
11
12
|
def render_css
|
@@ -18,14 +19,25 @@ class CmsContentController < ApplicationController
|
|
18
19
|
|
19
20
|
protected
|
20
21
|
|
22
|
+
def load_cms_site
|
23
|
+
@cms_site = CmsSite.find_by_hostname!(request.host.downcase)
|
24
|
+
rescue ActiveRecord::RecordNotFound
|
25
|
+
render :text => 'Site Not Found', :status => 404
|
26
|
+
end
|
27
|
+
|
21
28
|
def load_cms_page
|
22
|
-
@cms_page =
|
29
|
+
@cms_page = @cms_site.cms_pages.find_by_full_path!("/#{params[:cms_path]}")
|
30
|
+
return redirect_to(@cms_page.target_page.full_path) if @cms_page.target_page
|
23
31
|
rescue ActiveRecord::RecordNotFound
|
24
|
-
|
32
|
+
if @cms_page = @cms_site.cms_pages.find_by_full_path('/404')
|
33
|
+
render_html(404)
|
34
|
+
else
|
35
|
+
render :text => 'Page Not Found', :status => 404
|
36
|
+
end
|
25
37
|
end
|
26
38
|
|
27
39
|
def load_cms_layout
|
28
|
-
@cms_layout =
|
40
|
+
@cms_layout = @cms_site.cms_layouts.find(params[:id])
|
29
41
|
rescue ActiveRecord::RecordNotFound
|
30
42
|
render :nothing => true, :status => 404
|
31
43
|
end
|
data/app/models/cms_layout.rb
CHANGED
@@ -3,23 +3,23 @@ class CmsLayout < ActiveRecord::Base
|
|
3
3
|
acts_as_tree
|
4
4
|
|
5
5
|
# -- Relationships --------------------------------------------------------
|
6
|
+
belongs_to :cms_site
|
6
7
|
has_many :cms_pages, :dependent => :nullify
|
7
8
|
|
8
9
|
# -- Validations ----------------------------------------------------------
|
9
|
-
validates :
|
10
|
-
|
11
|
-
validates :content,
|
12
|
-
:presence => true
|
10
|
+
validates :cms_site_id, :presence => true
|
11
|
+
validates :label, :presence => true
|
12
|
+
validates :content, :presence => true
|
13
13
|
|
14
14
|
# -- Class Methods --------------------------------------------------------
|
15
15
|
# Tree-like structure for layouts
|
16
|
-
def self.options_for_select(cms_layout = nil, current_layout = nil, depth = 0, spacer = '. . ')
|
16
|
+
def self.options_for_select(cms_site, cms_layout = nil, current_layout = nil, depth = 0, spacer = '. . ')
|
17
17
|
out = []
|
18
|
-
[current_layout ||
|
18
|
+
[current_layout || cms_site.cms_layouts.roots].flatten.each do |layout|
|
19
19
|
next if cms_layout == layout
|
20
20
|
out << [ "#{spacer*depth}#{layout.label}", layout.id ]
|
21
21
|
layout.children.each do |child|
|
22
|
-
out += options_for_select(cms_layout, child, depth + 1, spacer)
|
22
|
+
out += options_for_select(cms_site, cms_layout, child, depth + 1, spacer)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
return out.compact
|
data/app/models/cms_page.rb
CHANGED
@@ -6,7 +6,10 @@ class CmsPage < ActiveRecord::Base
|
|
6
6
|
attr_accessor :cms_tags
|
7
7
|
|
8
8
|
# -- Relationships --------------------------------------------------------
|
9
|
+
belongs_to :cms_site
|
9
10
|
belongs_to :cms_layout
|
11
|
+
belongs_to :target_page,
|
12
|
+
:class_name => 'CmsPage'
|
10
13
|
has_many :cms_blocks,
|
11
14
|
:dependent => :destroy
|
12
15
|
accepts_nested_attributes_for :cms_blocks
|
@@ -16,6 +19,8 @@ class CmsPage < ActiveRecord::Base
|
|
16
19
|
after_save :sync_child_pages
|
17
20
|
|
18
21
|
# -- Validations ----------------------------------------------------------
|
22
|
+
validates :cms_site_id,
|
23
|
+
:presence => true
|
19
24
|
validates :label,
|
20
25
|
:presence => true
|
21
26
|
validates :slug,
|
@@ -26,15 +31,16 @@ class CmsPage < ActiveRecord::Base
|
|
26
31
|
:presence => true
|
27
32
|
validates :full_path,
|
28
33
|
:presence => true,
|
29
|
-
:uniqueness =>
|
34
|
+
:uniqueness => { :scope => :cms_site_id }
|
35
|
+
validate :validate_target_page
|
30
36
|
|
31
37
|
# -- Class Methods --------------------------------------------------------
|
32
38
|
# Tree-like structure for pages
|
33
|
-
def self.options_for_select(cms_page = nil, current_page = nil, depth = 0, spacer = '. . ')
|
34
|
-
return [] if (current_page ||=
|
39
|
+
def self.options_for_select(cms_site, cms_page = nil, current_page = nil, depth = 0, exclude_self = true, spacer = '. . ')
|
40
|
+
return [] if (current_page ||= cms_site.cms_pages.root) == cms_page && exclude_self || !current_page
|
35
41
|
out = [[ "#{spacer*depth}#{current_page.label}", current_page.id ]]
|
36
42
|
current_page.children.each do |child|
|
37
|
-
out += options_for_select(cms_page, child, depth + 1, spacer)
|
43
|
+
out += options_for_select(cms_site, cms_page, child, depth + 1, exclude_self, spacer)
|
38
44
|
end
|
39
45
|
return out.compact
|
40
46
|
end
|
@@ -59,6 +65,14 @@ protected
|
|
59
65
|
self.full_path = self.parent ? "#{self.parent.full_path}/#{self.slug}".squeeze('/') : '/'
|
60
66
|
end
|
61
67
|
|
68
|
+
def validate_target_page
|
69
|
+
return unless self.target_page
|
70
|
+
p = self
|
71
|
+
while p.target_page do
|
72
|
+
return self.errors.add(:target_page_id, 'Invalid Redirect') if (p = p.target_page) == self
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
62
76
|
# Forcing re-saves for child pages so they can update full_paths
|
63
77
|
def sync_child_pages
|
64
78
|
children.each{ |p| p.save! } if full_path_changed?
|