radiant-page_factory-extension 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/EXAMPLES.md +136 -0
- data/README.md +59 -0
- data/Rakefile +136 -0
- data/VERSION +1 -0
- data/app/controllers/admin/page_factories_controller.rb +42 -0
- data/app/helpers/admin/part_description_helper.rb +9 -0
- data/app/views/admin/page_factories/_page_factory.html.haml +4 -0
- data/app/views/admin/page_factories/index.haml +0 -0
- data/app/views/admin/page_parts/_part_description.html.haml +2 -0
- data/app/views/admin/pages/_add_child_column.html.haml +3 -0
- data/app/views/admin/pages/_edit_header.html.haml +1 -0
- data/app/views/admin/pages/_page_factories.html.haml +4 -0
- data/app/views/admin/pages/_page_factory_field.html.haml +1 -0
- data/config/locales/en.yml +3 -0
- data/config/routes.rb +5 -0
- data/db/migrate/20100321222140_add_page_factory.rb +9 -0
- data/lib/page_factory.rb +12 -0
- data/lib/page_factory/base.rb +81 -0
- data/lib/page_factory/manager.rb +120 -0
- data/lib/page_factory/page_extensions.rb +25 -0
- data/lib/page_factory/page_part_extensions.rb +9 -0
- data/lib/page_factory/pages_controller_extensions.rb +32 -0
- data/lib/tasks/page_factory_extension_tasks.rake +95 -0
- data/page_factory_extension.rb +25 -0
- data/public/javascripts/admin/dropdown.js +153 -0
- data/public/javascripts/admin/pagefactory.js +30 -0
- data/public/stylesheets/admin/page_factory.css +14 -0
- data/public/stylesheets/sass/admin/dropdown.sass +32 -0
- data/public/stylesheets/sass/modules/_gradient.sass +47 -0
- data/public/stylesheets/sass/modules/_rounded.sass +41 -0
- data/public/stylesheets/sass/modules/_shadow.sass +9 -0
- data/spec/controllers/admin/page_factories_controller_spec.rb +47 -0
- data/spec/controllers/admin/pages_controller_spec.rb +63 -0
- data/spec/helpers/admin/part_description_helper_spec.rb +42 -0
- data/spec/lib/manager_spec.rb +218 -0
- data/spec/lib/page_extensions_spec.rb +15 -0
- data/spec/models/page_factory_spec.rb +95 -0
- data/spec/models/page_spec.rb +27 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +36 -0
- metadata +128 -0
data/EXAMPLES.md
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
# Using PageFactory
|
2
|
+
|
3
|
+
PageFactory is meant to provide a way of defining content types without altering the page editing experience, or the way pages fundamentally behave. A content type is just a set of parts that you can re-use to create many pages with the same structure.
|
4
|
+
|
5
|
+
Let's say I'm creating a Radiant site for my company, and I need to create an employee directory. I'll have a lot of pages that represent individual employees, and each page will need the same basic parts: first name, last name, and biography.
|
6
|
+
|
7
|
+
Rather than add these parts to every employee page, it would be nice if I could simply get a new page with these parts already added. Page Factory lets me define "factories" which will set up my new pages exactly the way I want. I can have multiple factories, and I can make changes to existing factories and ask them to update my existing content.
|
8
|
+
|
9
|
+
## Creating new factories
|
10
|
+
|
11
|
+
The first thing I'll do (after installing PageFactory and running `rake db:migrate:extensions`) is to create a factory for "Employee" pages. I'll create a file called "employee_page_factory.rb" (the `_page_factory` suffix is mandatory.) I can put this in the app/models/ or lib/ directory of any extension, or a lib/ directory at the root of my Radiant project.
|
12
|
+
|
13
|
+
I need to tell my factory what parts I want:
|
14
|
+
|
15
|
+
class EmployeePageFactory < PageFactory::Base
|
16
|
+
part 'first name'
|
17
|
+
part 'last name'
|
18
|
+
part 'biography'
|
19
|
+
end
|
20
|
+
|
21
|
+
I visit /admin/pages, and click "Add Child." Hey, there's a popup here asking me what kind of page to add! I select "Employee Page" and I'm taken to a new page. The first name, last name, and biography parts are waiting for me! Neat!
|
22
|
+
|
23
|
+
But I don't need the default "extended" part on my employees page. Let's get rid of it:
|
24
|
+
|
25
|
+
class EmployeePageFactory < PageFactory::Base
|
26
|
+
part 'first name'
|
27
|
+
part 'last name'
|
28
|
+
part 'biography'
|
29
|
+
remove 'extended'
|
30
|
+
end
|
31
|
+
|
32
|
+
Repeat the steps to add a new page, and the "extended" part is no longer taking up space.
|
33
|
+
|
34
|
+
## Additional part options
|
35
|
+
|
36
|
+
I'll be adding a page for each of my coworkers, but I want them to log in and fill out their own biographies. In the meantime, I want some placeholder text in the biography part, even if it's just dummy text. That should motivate everyone to actually fill it out.
|
37
|
+
|
38
|
+
I'll edit my page factory to add the dummy text:
|
39
|
+
|
40
|
+
class EmployeePageFactory < PageFactory::Base
|
41
|
+
part 'first name'
|
42
|
+
part 'last name'
|
43
|
+
part 'biography', :content => "Lorem ipsum dolor sit amet."
|
44
|
+
end
|
45
|
+
|
46
|
+
Now when I add a new Employee page, the biography field will be pre-populated with this dummy text. But I want to make it clear that people should replace this with actual content. (Not all of my coworkers speak Latin.) I can add a little helper text that will be shown on the "biography" part tab, in order to explain what this part is used for:
|
47
|
+
|
48
|
+
class EmployeePageFactory < PageFactory::Base
|
49
|
+
part 'first name'
|
50
|
+
part 'last name'
|
51
|
+
part 'biography', :content => "Lorem ipsum dolor sit amet.",
|
52
|
+
:description => "Please replace this with one or two paragraphs about yourself."
|
53
|
+
end
|
54
|
+
|
55
|
+
The helper text gets displayed right above the text field on the biography tab for all new Employee pages.
|
56
|
+
|
57
|
+
## Updating existing content
|
58
|
+
|
59
|
+
### Adding parts
|
60
|
+
|
61
|
+
I spent all day adding employee pages for each of my coworkers... and then my boss tells me that the employee pages should list people's department. I add a 'department' part to my EmployeePageFactory, but this won't affect any employee pages I've already created.
|
62
|
+
|
63
|
+
Luckily, I won't have to go back through each existing employee page to manually add a department part. I can run the following rake task:
|
64
|
+
|
65
|
+
$ rake radiant:extensions:page_factory:refresh:soft
|
66
|
+
|
67
|
+
This iterates over every page created with a factory and adds any parts that are listed in the page's factory but missing from the page. Now all of my existing Employee pages have been updated with an empty "department" part.
|
68
|
+
|
69
|
+
It's called a "soft" refresh because it adds parts, but it won't change or remove any content. If I had more than one factory and I only wanted to act on Employee pages, I could specify a particular factory:
|
70
|
+
|
71
|
+
$ rake radiant:extensions:page_factory:refresh:soft[employee]
|
72
|
+
|
73
|
+
That argument is the name of my factory class minus "page_factory," because this rake task is already long enough.
|
74
|
+
|
75
|
+
### Removing parts
|
76
|
+
|
77
|
+
The boss just changed her mind about displaying everyone's department. This always happens! No problem though, I can just as easily remove the extra part. I just remove it from my factory definition and run this task:
|
78
|
+
|
79
|
+
$ rake radiant:extensions:page_factory:refresh:hard[employee]
|
80
|
+
|
81
|
+
Unlike a soft refresh, a hard refresh _will_ alter or remove content. In this case, it goes through all of my Employee pages and removes any parts that aren't listed in the factory definition.
|
82
|
+
|
83
|
+
## Other factory options
|
84
|
+
|
85
|
+
### Descriptions
|
86
|
+
|
87
|
+
If you have a lot of factories, it might be helpful to add a description to each so that you remember what they're all used for.
|
88
|
+
|
89
|
+
class EmployeePageFactory < PageFactory::Base
|
90
|
+
description "An employee profile page."
|
91
|
+
|
92
|
+
part 'first name'
|
93
|
+
part 'last name'
|
94
|
+
...
|
95
|
+
end
|
96
|
+
|
97
|
+
This description appears in the factory selection popup.
|
98
|
+
|
99
|
+
### Default layouts
|
100
|
+
|
101
|
+
Our very talented designer has just sent me the markup for the employee page. I'd like to put this in a layout and assign it to all the employee pages -- that way I only have to edit it in one place if there are changes later. I create a new layout called "Employee" and paste in the markup. I can make this the default layout by passing its name to the factory:
|
102
|
+
|
103
|
+
class EmployeePageFactory < PageFactory::Base
|
104
|
+
layout "Employee"
|
105
|
+
|
106
|
+
part 'first name'
|
107
|
+
part 'last name'
|
108
|
+
part 'biography', :content => "Lorem ipsum dolor sit amet.",
|
109
|
+
:description => "..."
|
110
|
+
end
|
111
|
+
|
112
|
+
Now the Employee layout will be automatically selected whenever I create a new Employee page. If I want to update all of my previously created Employee pages to use this new layout, I can do this by running the hard refresh task.
|
113
|
+
|
114
|
+
### Default page classes
|
115
|
+
|
116
|
+
Sometimes it might be useful to set a default page class, if for instance I have a page factory that deals with Archive pages. That's just as easy:
|
117
|
+
|
118
|
+
class ArchivePageFactory < PageFactory::Base
|
119
|
+
page_class "ArchivePage"
|
120
|
+
end
|
121
|
+
|
122
|
+
Again, I'd have to run the hard refresh task to update any existing pages.
|
123
|
+
|
124
|
+
## Working with pages
|
125
|
+
|
126
|
+
Good news! Because PageFactory made it so easy to create and maintain our site, I was awarded the Lifetime Employee Achievement Award! As part of this, I get to have a photo on my employee page. I'll use this nice one of me in a dapper hat.
|
127
|
+
|
128
|
+
This will require an extra page part, to hold the URL for my photo. It will also require a slightly different layout, to hold the image tag.
|
129
|
+
|
130
|
+
Does this mean I need to create a new factory and recreate my own employee page? Nope! PageFactory was built with flexibility in mind, and doesn't prevent you from working with pages in the ways that you're used to.
|
131
|
+
|
132
|
+
I can just open up my page and add a new 'photo url' part, then change the layout to one that accommodates a photo. The EmployeePageFactory doesn't care what happens to employee pages after they've been created. And if they ever find out I've been filching copy paper and revoke my award, I can just as easily remove that extra part and change the layout back to a normal employee layout.
|
133
|
+
|
134
|
+
(I do have to be careful about running the hard refresh task, however. That will remove my photo part, because it isn't defined in the factory, and reset my layout to the default employee layout. I can safely run it as long as I specify another factory name.)
|
135
|
+
|
136
|
+
I can also add a plain old page with no factory and add/delete parts as usual -- I don't have to rely on a factory for everything. This makes it easy to add individual pages whenever I want.
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Page Factory
|
2
|
+
|
3
|
+
An experimental Radiant extension for defining content types/page templates. The intent is to stay light and reuse instead of rebuild.
|
4
|
+
|
5
|
+
There are three basic questions when dealing with content types in any CMS:
|
6
|
+
|
7
|
+
+ Content Definition: what parts make up a particular kind of page?
|
8
|
+
+ Templating: what's the markup for each set of parts?
|
9
|
+
+ Versioning: how do we track and share changes to definitions & templates?
|
10
|
+
|
11
|
+
Page Factory is meant to address the first point, defining pages. Templating and versioning can be achieved with existing extensions and don't need to be reinvented. I like the combination of Nested Layouts and File System Resources, but the goal is to create an extension that's agnostic on those matters.
|
12
|
+
|
13
|
+
## Goals
|
14
|
+
|
15
|
+
I'm using the word "Factory" very deliberately. A traditional "content type" is a model that's attached to a page for the page's entire lifespan. To some extent, the content type dictates what you can and cannot do with that page.
|
16
|
+
|
17
|
+
This is a different approach. I want a _factory_ that only cares about setting up new pages, and doesn't make any page modifications until I tell it to. I want to retain all of the flexibility that comes with Radiant.
|
18
|
+
|
19
|
+
I want the following behaviors in my solution:
|
20
|
+
|
21
|
+
### Flexibility
|
22
|
+
|
23
|
+
I want my factories to set up pages for me and then stay out of my way. Using factories shouldn't prevent me from creating a Plain Old Page with my own choice of parts; nor should they prevent me from modifying pages after they're created.
|
24
|
+
|
25
|
+
### Simplicity
|
26
|
+
|
27
|
+
Page factories shouldn't fundamentally alter the way Pages work. I don't want to overload the `:body` part for use as a layout container. Nor do I want to use a web interface to manipulate content types. A Page factory should be a regular Ruby class; I should be able to inherit or extend it.
|
28
|
+
|
29
|
+
### Modularity
|
30
|
+
|
31
|
+
I want my factories to respect the division between presentation and behavior. Factories can _suggest_ a Page class, but shouldn't prevent you from changing that class on new or existing records. I'd like to take a similar approach to layouts -- flexibility is a requirement, not an enhancement.
|
32
|
+
|
33
|
+
## Some use cases
|
34
|
+
|
35
|
+
In addition to the core task of defining content types, there are some specific cases I want Page Factory to address:
|
36
|
+
|
37
|
+
### Generic pages
|
38
|
+
|
39
|
+
I want to add a one-off page somewhere. In the past, generic pages have been catch-all content types with enough parts to fit any use case. They're ugly and hard to use.
|
40
|
+
|
41
|
+
I should be able to add a Plain Old Page without setting up a content type first. I should be able to add only those parts I need. I should be able to use the `:body` part to hold that page's unique markup, just like normal Radiant usage.
|
42
|
+
|
43
|
+
### Edge cases
|
44
|
+
|
45
|
+
There's a page that needs to look or behave just a little differently from others of its kind. Instead of making its content type pull double duty, or creating a content type to handle a single page, I should be able to switch this page to a different layout. Or use a different page class. Or add a single page part to it.
|
46
|
+
|
47
|
+
Page factories shouldn't have an opinion about any of those attributes until you tell it to take action on a page or set of pages.
|
48
|
+
|
49
|
+
## Usage
|
50
|
+
|
51
|
+
See EXAMPLES.md for a detailed walkthrough.
|
52
|
+
|
53
|
+
## Notes on implementation
|
54
|
+
|
55
|
+
+ **Syncing.** Because I'm not exposing these factories in the admin UI, there's no need to do this in real-time. Unless explicitly asked, the methods responsible for altering existing content ignore Plain Old Pages so that you have at least one type of Page that's always open to modification and not in any danger of being overwritten.
|
56
|
+
|
57
|
+
+ **Changing factories.** I decided not to implement a way to change a page's factory after creation. This is mostly because I felt adding a new element to the page edit interface wasn't in line with PageFactory's stated goal of changing as little as possible about page behavior. It was confusing to have both a 'Page Type' select and a factory/template/whatever select side-by-side.
|
58
|
+
|
59
|
+
Additionally, I haven't worked out how changing a page's factory should work. Do the parts get reassigned on the fly? What happens if the pages share some parts?
|
data/Rakefile
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |gem|
|
4
|
+
gem.name = "radiant-page_factory-extension"
|
5
|
+
gem.summary = %Q{Page Factory Extension for Radiant CMS}
|
6
|
+
gem.description = %Q{Page Factory is a small DSL for intelligently defining content types in Radiant CMS.}
|
7
|
+
gem.email = "josh@vitamin-j.com"
|
8
|
+
gem.homepage = "http://github.com/joshfrench/radiant-page_factory-extension"
|
9
|
+
gem.authors = ["Josh French"]
|
10
|
+
gem.add_dependency 'radiant', '~> 0.9.0'
|
11
|
+
end
|
12
|
+
rescue LoadError
|
13
|
+
puts "Jeweler (or a dependency) not available. This is only required if you plan to package page-factory as a gem."
|
14
|
+
end
|
15
|
+
|
16
|
+
# In rails 1.2, plugins aren't available in the path until they're loaded.
|
17
|
+
# Check to see if the rspec plugin is installed first and require
|
18
|
+
# it if it is. If not, use the gem version.
|
19
|
+
|
20
|
+
# Determine where the RSpec plugin is by loading the boot
|
21
|
+
unless defined? RADIANT_ROOT
|
22
|
+
ENV["RAILS_ENV"] = "test"
|
23
|
+
case
|
24
|
+
when ENV["RADIANT_ENV_FILE"]
|
25
|
+
require File.dirname(ENV["RADIANT_ENV_FILE"]) + "/boot"
|
26
|
+
when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
|
27
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../")}/config/boot"
|
28
|
+
else
|
29
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../")}/config/boot"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
require 'rake'
|
34
|
+
require 'rake/rdoctask'
|
35
|
+
require 'rake/testtask'
|
36
|
+
|
37
|
+
rspec_base = File.expand_path(RADIANT_ROOT + '/vendor/plugins/rspec/lib')
|
38
|
+
$LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
|
39
|
+
require 'spec/rake/spectask'
|
40
|
+
require 'cucumber'
|
41
|
+
require 'cucumber/rake/task'
|
42
|
+
|
43
|
+
# Cleanup the RADIANT_ROOT constant so specs will load the environment
|
44
|
+
Object.send(:remove_const, :RADIANT_ROOT)
|
45
|
+
|
46
|
+
extension_root = File.expand_path(File.dirname(__FILE__))
|
47
|
+
|
48
|
+
task :default => :spec
|
49
|
+
task :stats => "spec:statsetup"
|
50
|
+
|
51
|
+
desc "Run all specs in spec directory"
|
52
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
53
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
54
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
55
|
+
end
|
56
|
+
|
57
|
+
task :features => 'spec:integration'
|
58
|
+
|
59
|
+
namespace :spec do
|
60
|
+
desc "Run all specs in spec directory with RCov"
|
61
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
62
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
63
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
64
|
+
t.rcov = true
|
65
|
+
t.rcov_opts = ['--exclude', 'spec', '--rails']
|
66
|
+
end
|
67
|
+
|
68
|
+
desc "Print Specdoc for all specs"
|
69
|
+
Spec::Rake::SpecTask.new(:doc) do |t|
|
70
|
+
t.spec_opts = ["--format", "specdoc", "--dry-run"]
|
71
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
72
|
+
end
|
73
|
+
|
74
|
+
[:models, :controllers, :views, :helpers].each do |sub|
|
75
|
+
desc "Run the specs under spec/#{sub}"
|
76
|
+
Spec::Rake::SpecTask.new(sub) do |t|
|
77
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
78
|
+
t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
desc "Run the Cucumber features"
|
83
|
+
Cucumber::Rake::Task.new(:integration) do |t|
|
84
|
+
t.fork = true
|
85
|
+
t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'pretty')]
|
86
|
+
# t.feature_pattern = "#{extension_root}/features/**/*.feature"
|
87
|
+
t.profile = "default"
|
88
|
+
end
|
89
|
+
|
90
|
+
# Setup specs for stats
|
91
|
+
task :statsetup do
|
92
|
+
require 'code_statistics'
|
93
|
+
::STATS_DIRECTORIES << %w(Model\ specs spec/models)
|
94
|
+
::STATS_DIRECTORIES << %w(View\ specs spec/views)
|
95
|
+
::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers)
|
96
|
+
::STATS_DIRECTORIES << %w(Helper\ specs spec/views)
|
97
|
+
::CodeStatistics::TEST_TYPES << "Model specs"
|
98
|
+
::CodeStatistics::TEST_TYPES << "View specs"
|
99
|
+
::CodeStatistics::TEST_TYPES << "Controller specs"
|
100
|
+
::CodeStatistics::TEST_TYPES << "Helper specs"
|
101
|
+
::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
|
102
|
+
end
|
103
|
+
|
104
|
+
namespace :db do
|
105
|
+
namespace :fixtures do
|
106
|
+
desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
|
107
|
+
task :load => :environment do
|
108
|
+
require 'active_record/fixtures'
|
109
|
+
ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
|
110
|
+
(ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'spec', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
|
111
|
+
Fixtures.create_fixtures('spec/fixtures', File.basename(fixture_file, '.*'))
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
desc 'Generate documentation for the page_factory extension.'
|
119
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
120
|
+
rdoc.rdoc_dir = 'rdoc'
|
121
|
+
rdoc.title = 'PageFactoryExtension'
|
122
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
123
|
+
rdoc.rdoc_files.include('README')
|
124
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
125
|
+
end
|
126
|
+
|
127
|
+
# For extensions that are in transition
|
128
|
+
desc 'Test the page_factory extension.'
|
129
|
+
Rake::TestTask.new(:test) do |t|
|
130
|
+
t.libs << 'lib'
|
131
|
+
t.pattern = 'test/**/*_test.rb'
|
132
|
+
t.verbose = true
|
133
|
+
end
|
134
|
+
|
135
|
+
# Load any custom rakefiles for extension
|
136
|
+
Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Admin::PageFactoriesController < ApplicationController
|
2
|
+
helper_method :factory_link
|
3
|
+
|
4
|
+
def index
|
5
|
+
@page = Page.find_by_id(params[:page])
|
6
|
+
@factories = factories
|
7
|
+
|
8
|
+
respond_to do |format|
|
9
|
+
format.html { render :partial => '/admin/page_factories/page_factory', :collection => @factories }
|
10
|
+
format.js { render :partial => '/admin/page_factories/page_factory', :collection => @factories }
|
11
|
+
format.json { render :json => @factories.to_json() }
|
12
|
+
format.xml { render :json => @factories.to_xml() }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
##
|
18
|
+
# If you need to limit what factories can be selected, alias chain this
|
19
|
+
# method. The current user and @page (the page you're adding a child to)
|
20
|
+
# are available here, so you can filter according to @page.class_name,
|
21
|
+
# @page.page_factory, current_user roles, etc.
|
22
|
+
#
|
23
|
+
# @return [Array] an array of factory classes which you may then modify
|
24
|
+
#
|
25
|
+
# @example Don't let designers add Archive pages
|
26
|
+
# def factories_with_permissions
|
27
|
+
# if current_user.admin?
|
28
|
+
# factories_without_permissions
|
29
|
+
# else
|
30
|
+
# factories_without_permissions.reject { |f| f.page_class == 'ArchivePage' }
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
# alias_method_chain :factories, :permissions
|
34
|
+
def factories
|
35
|
+
[PageFactory::Base, *PageFactory::Base.descendants.sort { |a,b| a.name <=> b.name }]
|
36
|
+
end
|
37
|
+
|
38
|
+
def factory_link(factory=PageFactory::Base)
|
39
|
+
args = { :factory => factory < PageFactory::Base ? factory : nil }
|
40
|
+
@page.nil? ? new_admin_page_path(args) : new_admin_page_child_path(@page, args)
|
41
|
+
end
|
42
|
+
end
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
%h1== #{controller.template_name.capitalize} #{(@page.page_factory || PageFactory::Base).template_name}
|
@@ -0,0 +1 @@
|
|
1
|
+
= hidden_field_tag 'page[page_factory]', @page.try(:page_factory) || params[:factory]
|
data/config/routes.rb
ADDED
data/lib/page_factory.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module PageFactory
|
2
|
+
def self.current_factory
|
3
|
+
@current_factory ||= PageFactory::Base
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.current_factory=(factory)
|
7
|
+
factory = factory.constantize if factory.is_a?(String)
|
8
|
+
if factory.nil? or factory <= PageFactory::Base
|
9
|
+
@current_factory = factory
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|