cadmus 0.4.4 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## cadmus 0.4.6 (07-15-2013)
2
+
3
+ * Changes for Rails 4 compatibility:
4
+ ** Allow PUT or PATCH for the update action
5
+ ** Implement a page_params protected method in page controllers, which you can override to get strong_parameters support
6
+
7
+ ## cadmus 0.4.5 (03-04-2013)
8
+
9
+ * Change all the other uses of ^ and $ in regexes to \A and \z
10
+ * Change scope to use a lambda for Rails 4 compatibility
11
+
12
+ ## cadmus 0.4.4 (03-04-2013)
13
+
14
+ * Change some uses of ^ and $ in regexes to \A and \z
15
+
1
16
  ## cadmus 0.4.3 (06-17-2012)
2
17
 
3
18
  * Add a cadmus:views generator to make view customization easier
data/README.md CHANGED
@@ -21,8 +21,10 @@ instead, just use forward-slash characters in the page slug to simulate folders,
21
21
 
22
22
  First, add Cadmus to your Gemfile:
23
23
 
24
- gem 'cadmus'
25
- gem 'redcarpet' # (required only if you intend to use Cadmus' Markdown support)
24
+ ```ruby
25
+ gem 'cadmus'
26
+ gem 'redcarpet' # (required only if you intend to use Cadmus' Markdown support)
27
+ ```
26
28
 
27
29
  The next step is to create a Page model. Your app can have multiple Page models if you like, but for this example, we'll just
28
30
  create one.
@@ -32,24 +34,55 @@ create one.
32
34
  You'll need to tweak the generated migration and model slightly. In the migration, after the `create_pages` block, add a
33
35
  unique index on the parent and slug columns:
34
36
 
35
- add_index :pages, [:parent_type, :parent_id, :slug], :unique => true
37
+ ```ruby
38
+ add_index :pages, [:parent_type, :parent_id, :slug], :unique => true
39
+ ```
36
40
 
37
41
  And in the model, add a `cadmus_page` declaration:
38
42
 
39
- class Page < ActiveRecord::Base
40
- cadmus_page
41
- end
43
+ ```ruby
44
+ class Page < ActiveRecord::Base
45
+ cadmus_page
46
+ end
47
+ ```
42
48
 
43
49
  You'll need a controller to deal with your pages. Here's a minimal example of one:
44
50
 
45
- class PagesController < ApplicationController
46
- include Cadmus::PagesController
47
-
48
- protected
49
- def page_class
50
- Page
51
- end
52
- end
51
+ ```ruby
52
+ class PagesController < ApplicationController
53
+ include Cadmus::PagesController
54
+
55
+ protected
56
+ def page_class
57
+ Page
58
+ end
59
+ end
60
+ ```
61
+
62
+ If you're on Rails 4 (or using the `strong_parameters` gem) you'll probably want to use forbidden attributes protection.
63
+ Here's how you do that:
64
+
65
+ ```ruby
66
+ class Page < ActiveRecord::Base
67
+ include ActiveModel::ForbiddenAttributesProtection
68
+ cadmus_page
69
+ end
70
+ ```
71
+
72
+ ```ruby
73
+ class PagesController < ApplicationController
74
+ include Cadmus::PagesController
75
+
76
+ protected
77
+ def page_params
78
+ params.require(:page).permit(:name, :slug, :content)
79
+ end
80
+
81
+ def page_class
82
+ Page
83
+ end
84
+ end
85
+ ```
53
86
 
54
87
  `Cadmus::PagesController` automatically adds the seven RESTful resource methods to your controller. It requires that you
55
88
  define a `page_class` method that returns the class for pages it's dealing with. (This could potentially return different
@@ -58,9 +91,11 @@ types of page.)
58
91
 
59
92
  Finally, you'll need to create routes for this controller. Cadmus provides a built-in helper for that:
60
93
 
61
- MyApp::Application.routes.draw do
62
- cadmus_pages
63
- end
94
+ ```ruby
95
+ MyApp::Application.routes.draw do
96
+ cadmus_pages
97
+ end
98
+ ```
64
99
 
65
100
  This will create the following routes:
66
101
 
@@ -68,6 +103,7 @@ This will create the following routes:
68
103
  * GET /pages/new => PagesController#new
69
104
  * POST /pages => PagesController#create
70
105
  * GET /pages/slug => PagesController#show
106
+ * PATCH /pages/slug => PagesController#update
71
107
  * PUT /pages/slug => PagesController#update
72
108
  * DELETE /pages/slug => PagesController#destroy
73
109
 
@@ -76,26 +112,30 @@ This will create the following routes:
76
112
  The pages controller is where you'll need to hook into any authorization or authentication system your app might use.
77
113
  We use CanCan, so here's an example of how we do that:
78
114
 
79
- class PagesController < ApplicationController
80
- include Cadmus::PagesController
81
-
82
- authorize_resource :page
83
-
84
- protected
85
- def page_class
86
- Page
87
- end
88
- end
115
+ ```ruby
116
+ class PagesController < ApplicationController
117
+ include Cadmus::PagesController
118
+
119
+ authorize_resource :page
120
+
121
+ protected
122
+ def page_class
123
+ Page
124
+ end
125
+ end
126
+ ```
127
+
128
+ ```ruby
129
+ class Ability
130
+ def initialize(user)
131
+ can :read, Page
132
+ return unless user
89
133
 
90
- class Ability
91
- def initialize(user)
92
- can :read, Page
93
- return unless user
94
-
95
- # in this example, we've added an owner_id column to our Page model
96
- can :manage, Page, :owner_id => user.id
97
- end
98
- end
134
+ # in this example, we've added an owner_id column to our Page model
135
+ can :manage, Page, :owner_id => user.id
136
+ end
137
+ end
138
+ ```
99
139
 
100
140
  Easy-peasy. You can use other authorization plugins in a similar way - with Cadmus, you control the CMS models,
101
141
  controllers and routes, so you can add whatever code is appropriate for your app.
@@ -108,49 +148,55 @@ content pages as well.
108
148
 
109
149
  You already have the following routes set up in your routes.rb file:
110
150
 
111
- DugoutCoach::Application.routes.draw do
112
- resources :teams do
113
- resources :players
114
- resources :schedule
115
- end
116
-
117
- cadmus_pages # for global pages on your site
118
- end
151
+ ```ruby
152
+ DugoutCoach::Application.routes.draw do
153
+ resources :teams do
154
+ resources :players
155
+ resources :schedule
156
+ end
157
+
158
+ cadmus_pages # for global pages on your site
159
+ end
160
+ ```
119
161
 
120
162
  So, for example, the URL for the Cambridge Cosmonauts might be http://dugoutcoach.net/teams/cosmonauts. They also
121
163
  have http://dugoutcoach.net/teams/cosmonauts/players and http://dugoutcoach.net/teams/cosmonauts/schedule.
122
164
 
123
165
  You can add a "pages" namespace pretty easily:
124
166
 
125
- DugoutCoach::Application.routes.draw do
126
- resources :teams do
127
- resources :players
128
- resources :schedule
129
- cadmus_pages :controller => :team_pages
130
- end
131
-
132
- cadmus_pages
133
- end
167
+ ```ruby
168
+ DugoutCoach::Application.routes.draw do
169
+ resources :teams do
170
+ resources :players
171
+ resources :schedule
172
+ cadmus_pages :controller => :team_pages
173
+ end
174
+
175
+ cadmus_pages
176
+ end
177
+ ```
134
178
 
135
179
  Now you have a way of separating team-specific pages from global pages on the site. The URLs for these pages might be,
136
180
  for example, http://dugoutcoach.net/teams/cosmonauts/directions, or
137
181
  http://dugoutcoach.net/teams/cosmonauts/promotions/free-hat-day (remember, Cadmus slugs can contain slashes). We'll
138
182
  now need a TeamPages controller to handle these:
139
183
 
140
- class TeamPagesController < ApplicationController
141
- include Cadmus::PagesController
142
-
143
- self.page_parent_class = Team # page's parent is a Team
144
- self.page_parent_name = "team" # parent ID is in params[:team_id]
145
- self.find_parent_by = "slug" # parent ID is the Team's "slug" field rather than "id"
146
-
147
- authorize_resource :page
148
-
149
- protected
150
- def page_class
151
- Page
152
- end
153
- end
184
+ ```ruby
185
+ class TeamPagesController < ApplicationController
186
+ include Cadmus::PagesController
187
+
188
+ self.page_parent_class = Team # page's parent is a Team
189
+ self.page_parent_name = "team" # parent ID is in params[:team_id]
190
+ self.find_parent_by = "slug" # parent ID is the Team's "slug" field rather than "id"
191
+
192
+ authorize_resource :page
193
+
194
+ protected
195
+ def page_class
196
+ Page
197
+ end
198
+ end
199
+ ```
154
200
 
155
201
  Note that for this example, we've kept the same `Page` class for both controllers. We could have also created a
156
202
  separate `TeamPage` model, but that's not required.
@@ -162,15 +208,17 @@ in them just because they created them themselves?
162
208
 
163
209
  Chill out, Cosmonauts. Cadmus makes it easy:
164
210
 
165
- DugoutCoach::Application.routes.draw do
166
- resources :teams do
167
- resources :players
168
- resources :schedule
169
- cadmus_pages :controller => :team_pages, :shallow => true
170
- end
171
-
172
- cadmus_pages
173
- end
211
+ ```ruby
212
+ DugoutCoach::Application.routes.draw do
213
+ resources :teams do
214
+ resources :players
215
+ resources :schedule
216
+ cadmus_pages :controller => :team_pages, :shallow => true
217
+ end
218
+
219
+ cadmus_pages
220
+ end
221
+ ```
174
222
 
175
223
  Now the PagesController's `show`, `edit`, `update`, and `destroy` actions don't use the "/pages/" part of the URL. The
176
224
  URLs now look like this:
@@ -203,35 +251,40 @@ help them by providing them with a Liquid template variable they can use like so
203
251
 
204
252
  To do this, you'll need to expose `team` as a Liquid assign variable:
205
253
 
206
- class TeamPagesController < ApplicationController
207
- include Cadmus::PagesController
208
-
209
- self.page_parent_class = Team # page's parent is a Team
210
- self.page_parent_name = "team" # parent ID is in params[:team_id]
211
- self.find_parent_by = "slug" # parent ID is the Team's "slug" field rather than "id"
212
-
213
- authorize_resource :page
214
-
215
- protected
216
- def page_class
217
- Page
218
- end
219
-
220
- def liquid_assigns
221
- { :team => @page.parent }
222
- end
223
- end
254
+ ```ruby
255
+ class TeamPagesController < ApplicationController
256
+ include Cadmus::PagesController
257
+
258
+ self.page_parent_class = Team # page's parent is a Team
259
+ self.page_parent_name = "team" # parent ID is in params[:team_id]
260
+ self.find_parent_by = "slug" # parent ID is the Team's "slug" field rather than "id"
261
+
262
+ authorize_resource :page
263
+
264
+ protected
265
+
266
+ def page_class
267
+ Page
268
+ end
269
+
270
+ def liquid_assigns
271
+ { :team => @page.parent }
272
+ end
273
+ end
274
+ ```
224
275
 
225
276
  Defining a `liquid_assigns` method will cause Cadmus to use the return value of that method as the Liquid assigns hash.
226
277
  (Similarly, you can define `liquid_filters` and `liquid_registers` methods that do what they say on the tin.)
227
278
 
228
279
  You'll also need to make your Team model usable from Liquid. The simplest way to do that is using `liquid_methods`:
229
280
 
230
- class Team < ActiveRecord::Base
231
- liquid_methods :name, :uniform_color
232
-
233
- # everything else in your model...
234
- end
281
+ ```ruby
282
+ class Team < ActiveRecord::Base
283
+ liquid_methods :name, :uniform_color
284
+
285
+ # everything else in your model...
286
+ end
287
+ ```
235
288
 
236
289
  You could also define a `to_liquid` method that returns a `Liquid::Drop` subclass for Teams, if you need to do things
237
290
  more complicated than just return data values.
@@ -17,7 +17,7 @@
17
17
  <div class="field">
18
18
  <%= f.label :slug, "URL" %>
19
19
  <p>
20
- <%= url_for(:action => 'show', :page_glob => "slug", :only_path => false).sub(/slug$/, '') %>
20
+ <%= url_for(:action => 'show', :page_glob => "slug", :only_path => false).sub(/slug\Z/, '') %>
21
21
  <%= f.text_field :slug %>
22
22
  </p>
23
23
  </div>
@@ -94,7 +94,7 @@ module Cadmus
94
94
  end
95
95
 
96
96
  def new
97
- @page = page_scope.new(params[:page])
97
+ @page = page_scope.new(page_params)
98
98
 
99
99
  respond_to do |format|
100
100
  format.html { render 'cadmus/pages/new' }
@@ -108,7 +108,7 @@ module Cadmus
108
108
  end
109
109
 
110
110
  def create
111
- @page = page_scope.new(params[:page])
111
+ @page = page_scope.new(page_params)
112
112
 
113
113
  respond_to do |format|
114
114
  if @page.save
@@ -126,7 +126,7 @@ module Cadmus
126
126
 
127
127
  def update
128
128
  respond_to do |format|
129
- if @page.update_attributes(params[:page])
129
+ if @page.update_attributes(page_params)
130
130
  dest = { :action => 'show', :page_glob => @page.slug }
131
131
  format.html { redirect_to(dest, :notice => 'Page was successfully updated.') }
132
132
  format.xml { head :ok }
@@ -211,6 +211,10 @@ module Cadmus
211
211
  @page_scope ||= page_parent ? page_parent.pages : page_class.global
212
212
  end
213
213
 
214
+ def page_params
215
+ params[:page]
216
+ end
217
+
214
218
  def load_parent_and_page
215
219
  if params[:page_glob]
216
220
  @page = page_scope.find_by_slug(params[:page_glob])
data/lib/cadmus/page.rb CHANGED
@@ -38,7 +38,7 @@ module Cadmus
38
38
  validates_uniqueness_of slug_field, :scope => [:parent_id, :parent_type]
39
39
  validates_exclusion_of slug_field, :in => %w(pages edit)
40
40
 
41
- scope :global, :conditions => { :parent_id => nil, :parent_type => nil }
41
+ scope :global, lambda { where(:parent_id => nil, :parent_type => nil) }
42
42
 
43
43
  class_eval do
44
44
  def liquid_template
@@ -16,7 +16,7 @@ module Cadmus
16
16
  # application. So we have to always pass this constraint if we're testing.
17
17
  return true if page_glob.nil? && Rails.env.test?
18
18
 
19
- page_glob.sub(/^\//, '').split(/\//).all? do |part|
19
+ page_glob.sub(/\A\//, '').split(/\//).all? do |part|
20
20
  part =~ /\A[a-z][a-z0-9\-]*\z/
21
21
  end
22
22
  end
@@ -55,7 +55,7 @@ ActionDispatch::Routing::Mapper.class_eval do
55
55
  page_actions = Proc.new do
56
56
  get "*page_glob/edit" => "#{controller}#edit", :as => 'edit_page', :constraints => slug_constraint
57
57
  get "*page_glob" => "#{controller}#show", :as => 'page', :constraints => slug_constraint
58
- put "*page_glob" => "#{controller}#update", :constraints => slug_constraint
58
+ match "*page_glob" => "#{controller}#update", :constraints => slug_constraint, :via => [:put, :patch]
59
59
  delete "*page_glob" => "#{controller}#destroy", :constraints => slug_constraint
60
60
  end
61
61
 
data/lib/cadmus/slugs.rb CHANGED
@@ -8,7 +8,7 @@ module Cadmus
8
8
  #
9
9
  # For example, +about-us/people+, +special-deals+, and +winter-2012+ are all valid slugs, but
10
10
  # +3-things+, +123+, +nobody-lives-here!+, and +/root-page+ aren't.
11
- SLUG_REGEX = /^([a-z][a-z0-9\-]*\/)*[a-z][a-z0-9\-]*$/
11
+ SLUG_REGEX = /\A([a-z][a-z0-9\-]*\/)*[a-z][a-z0-9\-]*\z/
12
12
 
13
13
  # Converts a string to a valid slug part by changing all whitespace to hyphens, converting all
14
14
  # upper-case letters to lower-case, removing all remaining non-alphanumeric, non-hyphen
@@ -19,7 +19,7 @@ module Cadmus
19
19
  # * "21 guns" becomes "guns"
20
20
  # * "We love you, Conrad!!!1" becomes "we-love-you-conrad1"
21
21
  def self.slugify(string)
22
- string.to_s.downcase.gsub(/\s+/, '-').gsub(/[^a-z0-9\-]/, '').sub(/^[^a-z]+/, '')
22
+ string.to_s.downcase.gsub(/\s+/, '-').gsub(/[^a-z0-9\-]/, '').sub(/\A[^a-z]+/, '')
23
23
  end
24
24
 
25
25
  # An extension for ActiveRecord::Base that adds a +has_slug+ method. This can also be
@@ -1,3 +1,3 @@
1
1
  module Cadmus
2
- VERSION = "0.4.4"
2
+ VERSION = "0.4.6"
3
3
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: cadmus
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.4.4
5
+ version: 0.4.6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Nat Budin
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-03-04 00:00:00.000000000 Z
13
+ date: 2013-07-15 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  version_requirements: !ruby/object:Gem::Requirement
@@ -102,4 +102,3 @@ signing_key:
102
102
  specification_version: 3
103
103
  summary: Embeddable CMS for Rails 3 apps
104
104
  test_files: []
105
- has_rdoc: