browsercms 3.0.1 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,193 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
5
+ <title></title>
6
+ <link rel="stylesheet" type="text/css" href="files/stylesheets/syntax.css" />
7
+ <script type="text/javascript" src="files/javascripts/code_highlighter.js"></script>
8
+ <script type="text/javascript" src="files/javascripts/highlighters.js"></script>
9
+ <style type="text/css">
10
+ body {
11
+ background: #FFFFFF url(images/bg.png) repeat-x scroll 0 0;
12
+ font-family: "Trebuchet MS", Helvetica, Verdana, Arial, sans-serif;
13
+ margin: 0;
14
+ padding: 0;
15
+ }
16
+
17
+ #page {
18
+ margin: 0 auto;
19
+ text-align: left;
20
+ width: 1000px;
21
+ }
22
+
23
+ #header {
24
+ height: 110px;
25
+ }
26
+
27
+ div.top_cap {
28
+ background: transparent url(images/top_cap.png) no-repeat scroll 0 0;
29
+ height: 10px;
30
+ }
31
+
32
+ #contentwrap {
33
+ background: transparent url(images/dot.png) repeat scroll 0 0;
34
+ float: left;
35
+ width: 1000px;
36
+ }
37
+
38
+ div.bottom_cap {
39
+ background: transparent url(images/bottom_cap.png) no-repeat scroll 0 0;
40
+ height: 9px;
41
+ }
42
+
43
+ div.top_cap_content {
44
+ background: transparent url(images/top_cap_content.png) no-repeat scroll 0 0;
45
+ height: 5px;
46
+ }
47
+
48
+ #content {
49
+ background-color: #FFFFFF;
50
+ margin: 0 5px;
51
+ padding: 0 10px;
52
+ }
53
+
54
+ div.title {
55
+ padding: 20px;
56
+ }
57
+
58
+ div.title h1 {
59
+ border-bottom: 3px solid #505358;
60
+ color: #FFFFFF;
61
+ font-size: 24pt;
62
+ font-weight: normal;
63
+ line-height: 1;
64
+ margin: 0 0 10px;
65
+ padding-bottom: 10px;
66
+ }
67
+
68
+ td.sidebar {
69
+ font-size: 8pt;
70
+ width: 165px;
71
+ padding: 5px;
72
+ }
73
+
74
+ td.sidebar ol {
75
+ margin-left: 20px;
76
+ padding: 0;
77
+ line-height: 1.5;
78
+ }
79
+
80
+ td.sidebar ol li {
81
+ margin: 0;
82
+ padding: 0;
83
+ }
84
+
85
+ td.sidebar ol li ul {
86
+ list-style-type: none;
87
+ padding-left: 10px;
88
+ }
89
+
90
+ td.guides {
91
+ font-size: 10pt;
92
+ width: 800px;
93
+ padding: 10px;
94
+ }
95
+
96
+ .code_container {
97
+ padding: 10px;
98
+ background: #eee;
99
+ border: 1px solid #ccc;
100
+ overflow: auto;
101
+ width: 760px;
102
+ }
103
+
104
+ pre, code {
105
+ overflow: auto;
106
+ white-space:pre;
107
+ }
108
+
109
+ </style>
110
+ </head>
111
+ <body>
112
+ <div id="page">
113
+ <div id="header">
114
+ <a href="index.html"><img style="border:0px" src="images/browsercms_logo.png" alt="BrowserCMS"/></a>
115
+ </div>
116
+ <div id="main">
117
+ <div class="top_cap"></div>
118
+ <div id="contentwrap">
119
+ <div class="title">
120
+ <h1></h1>
121
+ </div>
122
+ <div class="top_cap_content"></div>
123
+ <div id="content">
124
+ <table width="100%" cellpadding="0" cellspacing="0" border="0">
125
+ <tr>
126
+ <td class="sidebar" valign="top">
127
+ <div id="subCol">
128
+ <h3 class="chapter"><img src="images/chapters_icon.gif" alt="" />Chapters</h3>
129
+ <ol class="chapters">
130
+ </ol></div>
131
+ </td>
132
+ <td class="guides">
133
+
134
+ <h2>Using <span class="caps">CMS</span> Authentication</h2>
135
+ <p>When you create public controllers, you may want to take advantage of the <span class="caps">CMS</span> authentication system. Create an action that
136
+ looks like this:</p>
137
+ <div class="code_container"><code class="ruby">class MyNewController &lt; ApplicationController
138
+
139
+ # This adds methods to your controller to work with the authenticated user.
140
+ include Cms::Authentication::Controller
141
+
142
+ def do_something_interesting
143
+ # The current_user method looks up the user based on either a cookie, or session variable.
144
+ user = current_user
145
+
146
+ if user.guest?
147
+ redirect_to &quot;/system/access-denied&quot;
148
+ else
149
+ redirect_to &quot;/my_target/page&quot;
150
+ end
151
+ end
152
+ end</code></div>
153
+ <p>The current_user method is also available in Portlets (maybe), as well as in the view files for both portlets and templates.</p>
154
+ <h3>Understanding Guest users
155
+ Many visitors to a <span class="caps">CMS</span> site will not be logged in. These users are considered to be members of a special group, called &#8216;Guest&#8217;. This
156
+ group allows staff to set permissions for denying entry to specific sections. When you call the following:</h3>
157
+ <div class="code_container"><code class="ruby">user = current_user</code></div>
158
+ <p>if there the user is not logged in, a
159
+ dirty_workaround_for_notextile_2
160
+ object will be returned. This user has all the permissions of the guest group, which are
161
+ usually limited to viewing public sections.</p>
162
+ <h2>Working with the Content <span class="caps">API</span>
163
+ One of the central features that the content <span class="caps">API</span> adds to models is versioning and publishing. Each content block can either be published or in draft. The data for a block is split between two tables, the primary table and it&#8217;s version table. The primary table
164
+ stores the &#8216;live&#8217; version of a block, typically the last &#8216;Published&#8217; version of a block. The versions table stores all other versions, including future edits which are unpublished.</h2>
165
+ <h3>Differences between ActiveRecord and Content <span class="caps">API</span>
166
+ This can cause some confusion when using basic ActiveRecord operations, where you might not get what you expect. For example, suppose we create an Event Block</h3>
167
+ <div class="code_container"><code class="ruby">class Event &lt; ActiveRecord::Base
168
+ acts_as_content_block
169
+ end
170
+
171
+ event = Event.create!(:name=&gt;&quot;Event #1&quot;, :save_and_publish=&gt;true)
172
+ event.name = &quot;Event #2&quot;
173
+ event.save!
174
+
175
+ assert_equals &quot;Event #2&quot;, Event.find(event.id) # This is false, and will fail.</code></div>
176
+ <p>In this case, &#8220;Event #2&#8221; is a draft, stored in the &#8216;events_versions&#8217; table. To create and publish the event, you can do this:</p>
177
+ <div class="code_container"><code class="ruby">event = Event.create!(:name=&gt;&quot;Event #1&quot;, :save_and_publish=&gt;true)
178
+ event.name = &quot;Event #2&quot;
179
+ event.publish! # This will both publish and save the record.
180
+
181
+ assert_equals &quot;Event #2&quot;, Event.find(event.id) # This is now true.</code></div>
182
+ </td>
183
+ </tr>
184
+ </table>
185
+ </div>
186
+ </div>
187
+ <br clear="all"/>
188
+ <div class="bottom_cap"></div>
189
+ </div>
190
+ </div>
191
+ </body>
192
+ </html>
193
+
@@ -138,7 +138,17 @@
138
138
  <li>How to use helpers to add dynamic content to templates and partials</li>
139
139
  <li>How to use the <span class="caps">CMS</span>-specific form builder extensions</li>
140
140
  </ul>
141
-
141
+ <h2>Creating a template
142
+ Each page in BrowserCMS uses a single template, which is designed to provide overall layout structure of the page. Here&#8217;s the general process
143
+ that a design team might follow to create a <span class="caps">CMS</span> template.</h2>
144
+ <p>1. Start with a <span class="caps">PSD</span> or <span class="caps">JPG</span> of the design, which represents the end result of what the webpage should look like.
145
+ 2. Create a static html file which implements that design.
146
+ 3. When creating menus, use the same structural <span class="caps">HTML</span> markup as will be generated by the Menu <span class="caps">API</span>. (See Menu&#8217;s below)
147
+ 4. Change the file extension from .htm to .html.erb and add it as a template to the <span class="caps">CMS</span>.</p>
148
+ <h2>Menus
149
+ BrowserCMS provides an <span class="caps">API</span> to allow menus to be dynamically generated based on the sitemap. The purpose of this is to make
150
+ it easy to add new pages, without having to modify templates.</h2>
151
+ <div class="code_container"><code class="ruby">render_menu</code></div>
142
152
  </td>
143
153
  </tr>
144
154
  </table>
@@ -127,7 +127,7 @@
127
127
  <div id="subCol">
128
128
  <h3 class="chapter"><img src="images/chapters_icon.gif" alt="" />Chapters</h3>
129
129
  <ol class="chapters">
130
- <li><a href="#content-blocks">Content Blocks</a><ul></ul></li><li><a href="#creating-a-custom-content-block">Creating A Custom Content Block</a><ul></ul></li><li><a href="#creating-a-custom-portlet">Creating A Custom Portlet</a><ul><li><a href="#using-file-system-templates">Using File system templates</a></li><li><a href="#pre-selecting-a-handler">Pre-selecting a handler</a></li></ul></li><li><a href="#page-routes">Page Routes</a><ul></ul></li></ol></div>
130
+ <li><a href="#content-blocks">Content Blocks</a><ul></ul></li><li><a href="#creating-a-custom-content-block">Creating A Custom Content Block</a><ul><li><a href="#attribute-types">Attribute Types</a></li></ul></li><li><a href="#creating-a-custom-portlet">Creating A Custom Portlet</a><ul><li><a href="#using-file-system-templates">Using File system templates</a></li><li><a href="#pre-selecting-a-handler">Pre-selecting a handler</a></li></ul></li><li><a href="#page-routes">Page Routes</a><ul></ul></li></ol></div>
131
131
  </td>
132
132
  <td class="guides">
133
133
  <h2>BrowserCMS Developer Guide</h2>
@@ -170,6 +170,48 @@ end</code></div>
170
170
  <p>The form helper methods that are prefixed with <tt>cms_</tt> will wrap that form helper with the <span class="caps">CMS</span> styling and extra functionality. The <tt>cms_text_editor</tt> will show the user a <span class="caps">WYSIWYG</span> editor for editing <span class="caps">HTML</span>. Additional <span class="caps">CMS</span> form builder extensions are covered in the <a href="designer_guide.html">BrowserCMS Designer Guide</a>.</p>
171
171
  <p>The render template at <tt>app/views/cms/products/render.html.erb</tt> is the template that will be used to render the <span class="caps">HTML</span> when this product is placed directly on a page. It is also what is shown when you view a product within the content library of the <span class="caps">CMS</span>.</p>
172
172
  <p>As you will see in the next section, custom content blocks are often not placed directly on a page, instead the data of a product is displayed through a portlet. For this reason, a more informational display, similar to what is automatically generated by the generator, is what the render template often contains. Depending on what your content block is, you may want to place the content block directly on a page, in which case you would most likely customize the render template.</p>
173
+ <h4 id="attribute-types">2.1 Attribute Types
174
+ This section covers some of the different attribute types that Content Blocks can have. Each attribute represents a
175
+ persistent column in the database, will appear as an editable control on the <em>form.html.erb, and may also need to need to be configured
176
+ on the content</em>block itself.</h4>
177
+ <p>List of Content Types</p>
178
+ <ul>
179
+ <li>Text Fields</li>
180
+ <li>Text Areas</li>
181
+ <li>Drop Down (Select)</li>
182
+ <li>Text Editor (<span class="caps">WYWIWYG</span>)</li>
183
+ <li>Attachment (File Upload)</li>
184
+ <li>Tag List (Allow</li>
185
+ <li>Date Picker</li>
186
+ </ul>
187
+ <h5 id="drop-down--selects">2.1.1 Drop Down / Selects
188
+ This is similar to the traditional &#8216;select&#8217; helper, it renders a stylized select control which allows users to choose one item from a list.</h5>
189
+ <h6 id="cms-drop-down">2.1.1.1 cms_drop_down
190
+ In _form.html.erb:</h6>
191
+ <div class="code_container"><code class="html">&lt;%= f.cms_drop_down :category_id, Category.all(:order =&gt; &quot;name&quot;).map{|c| [c.name, c.id]},
192
+ :prompt =&gt; &quot;Select a Category&quot;, :label =&gt; &quot;Category&quot;,
193
+ :instructions=&gt;&quot;Determines which category is used on the homepage.&quot; %&gt;</code></div>
194
+ <p>In product.rb:</p>
195
+ <div class="code_container"><code class="ruby">class Product &lt; ActiveRecord::Base
196
+ belongs_to :category
197
+ end</code></div>
198
+ <h5 id="attachments">2.1.2 Attachments
199
+ Each content block can have a single file attachment, which will allow users to upload files into the content repository. After uploading, the file will be
200
+ stored in a section within the <span class="caps">CMS</span>. Since sections determine permissions, this will allow you to control which users can access the file itself. Attached files
201
+ will have their own versioning history, which will keep track of changes.</h5>
202
+ <h6 id="cms-file-field">2.1.2.1 cms_file_field
203
+ This helper will create a stylized file upload file. An uploaded file will be associated with the content_block to which it is attached.</h6>
204
+ <p>In _form.html.erb (View)</p>
205
+ <div class="code_container"><code class="html">&lt;%= f.cms_file_field :attachment_file, :label =&gt; &quot;File&quot; %&gt;</code></div>
206
+ <p>In product.rb (Model)</p>
207
+ <div class="code_container"><code class="ruby">class Product &lt; ActiveRecord::Base
208
+ acts_as_content_block :belongs_to_attachment =&gt; true
209
+ end</code></div>
210
+ <p>In create_products.rb (Migration)</p>
211
+ <div class="code_container"><code class="ruby">create_content_table :products do |t|
212
+ t.belongs_to :attachment
213
+ t.integer :attachment_version
214
+ end</code></div>
173
215
  <h3 id="creating-a-custom-portlet">3 Creating A Custom Portlet</h3>
174
216
  <p>Once you have created the product content block and created a few products in the content library, you need a way to display them on a page. To do that, you will want to create a portlet.</p>
175
217
  <p>A portlet is used to display dynamic data on a page. A portlet is a content block. A portlet will typically perform some kind of database query in the render method and then render it&#8217;s view. One difference between a portlet and typical content block is that each instance of a portlet can have a unique template because that template is stored as data along with the portlet. Let&#8217;s generate a portlet to display the most recently created products:</p>
@@ -155,7 +155,7 @@ $ script/server</code></div>
155
155
  <div class="code_container"><code class="html">$ rails my_new_project_name -d mysql -m http://browsercms.org/templates/demo.rb
156
156
  $ cd my_new_project_name
157
157
  $ script/server</code></div>
158
- <p>Here we specify the -m mysql flag to rails, which will create our project using MySQL. You need to have the mysql gem installed for this to work.</p>
158
+ <p>Here we specify the -d mysql flag to rails, which will create our project using MySQL. You need to have the mysql gem installed for this to work.</p>
159
159
  <h4 id="using-your-site">2.3 Using your Site</h4>
160
160
  <p>Open your browser to <a href="http://localhost:3000/cms">http://localhost:3000/cms</a> to log into the admin for the <span class="caps">CMS</span>. Enter the default username/password (in development mode) is username=cmsadmin, password=cmsadmin. You should be now be logged in, viewing the home page of the site. You can now edit or add new content via the admin interface.</p>
161
161
  <p>To learn more about the types of things you can do with BrowserCMS, see the <a href="user_guide.html">User&#8217;s Guide</a>.</p>
@@ -8,8 +8,9 @@ module Cms
8
8
  !current_user.nil? && !current_user.guest?
9
9
  end
10
10
 
11
- # Accesses the current user from the session.
12
- # If the user is not logged in, this will be set to the guest user
11
+ # Accesses the current user from the session or 'remember me' cookie.
12
+ # If the user is not logged in, this will be set to the guest user, which represents a public
13
+ # user, who will likely have more limited permissions
13
14
  def current_user
14
15
  @current_user ||= begin
15
16
  User.current = (login_from_session || login_from_cookie || User.guest)
@@ -1,14 +1,19 @@
1
1
  module ActiveRecord
2
2
  module ConnectionAdapters # :nodoc:
3
3
  module SchemaStatements
4
- def create_versioned_table(table_name, options={}, &block)
4
+
5
+ # Pass in ":versioned => false" in the options hash to create a non-versioned table.
6
+ def create_content_table(table_name, options={}, &block)
5
7
 
6
8
  #Do the primary table
7
9
  t = TableDefinition.new(self)
8
10
  t.primary_key(options[:primary_key] || Base.get_primary_key(table_name)) unless options[:id] == false
9
11
 
10
- t.integer :version
11
- t.integer :lock_version, :default => 0
12
+ unless options[:versioned] == false
13
+ t.integer :version
14
+ t.integer :lock_version, :default => 0
15
+ end
16
+
12
17
  yield t
13
18
 
14
19
  # Blocks currently must have a name column, otherwise the UI fails in several places.
@@ -21,35 +26,40 @@ module ActiveRecord
21
26
  t.integer :created_by_id
22
27
  t.integer :updated_by_id
23
28
  t.timestamps
24
-
25
29
 
26
30
  create_table_from_definition(table_name, options, t)
27
31
 
28
- #Do the versions table
29
- vt = TableDefinition.new(self)
30
- vt.primary_key(options[:primary_key] || Base.get_primary_key(table_name)) unless options[:id] == false
32
+ unless options[:versioned] == false
33
+ #Do the versions table
34
+ vt = TableDefinition.new(self)
35
+ vt.primary_key(options[:primary_key] || Base.get_primary_key(table_name)) unless options[:id] == false
31
36
 
32
- vt.integer "#{table_name.to_s.singularize}_id".to_sym
33
- vt.integer :version
34
- yield vt
37
+ vt.integer "#{table_name.to_s.singularize}_id".to_sym
38
+ vt.integer :version
39
+ yield vt
35
40
 
36
- # Create implicit name column in version table as well.
37
- vt.string :name unless vt[:name]
41
+ # Create implicit name column in version table as well.
42
+ vt.string :name unless vt[:name]
38
43
 
39
- vt.boolean :published, :default => false
40
- vt.boolean :deleted, :default => false
41
- vt.boolean :archived, :default => false
42
- vt.string :version_comment
43
- vt.integer :created_by_id
44
- vt.integer :updated_by_id
45
- vt.timestamps
46
-
44
+ vt.boolean :published, :default => false
45
+ vt.boolean :deleted, :default => false
46
+ vt.boolean :archived, :default => false
47
+ vt.string :version_comment
48
+ vt.integer :created_by_id
49
+ vt.integer :updated_by_id
50
+ vt.timestamps
47
51
 
48
-
49
- create_table_from_definition("#{table_name.to_s.singularize}_versions".to_sym, options, vt)
52
+ create_table_from_definition("#{table_name.to_s.singularize}_versions".to_sym, options, vt)
53
+ end
50
54
 
51
55
  end
52
-
56
+
57
+ #
58
+ # @deprecated - create_versioned_table should be considered deprecated and may be removed in a future version.
59
+ # Use create_content_table instead in your migrations
60
+ #
61
+ alias :create_versioned_table :create_content_table
62
+
53
63
  def create_table_from_definition(table_name, options, table_definition)
54
64
  if options[:force] && table_exists?(table_name)
55
65
  drop_table(table_name, options)
@@ -66,7 +76,13 @@ module ActiveRecord
66
76
  drop_table "#{table_name.singularize}_versions".to_sym
67
77
  drop_table table_name
68
78
  end
69
-
79
+
80
+ # Adds a column to both the primary and versioned table. Save needing two calls.
81
+ # This is only needed if your content block is versioned, otherwise add_column will work just fine.
82
+ def add_content_column(table_name, column_name, type, options={})
83
+ add_column table_name, column_name, type, options
84
+ add_column "#{table_name.to_s.singularize}_versions".to_sym, column_name, type, options
85
+ end
70
86
  end
71
87
  end
72
- end
88
+ end
data/lib/cms/routes.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  module Cms::Routes
2
-
2
+
3
+ #
4
+ # content_block_name - Should be a plural symbol matching the name of the content_block, like :dogs or donation_statuses
5
+ #
3
6
  def content_blocks(content_block_name, options={}, &block)
4
7
  content_block = content_block_name.to_s.classify.constantize
5
8
  resources(*[content_block_name, default_routes_for_content_block(content_block).deep_merge(options)], &block)
data/lib/tasks/db.rake CHANGED
@@ -1,6 +1,10 @@
1
1
  require 'find'
2
2
 
3
3
  namespace :db do
4
+
5
+ desc "Drop, create and migrate the database"
6
+ task :redo => ["db:drop", "db:create", "db:migrate"]
7
+
4
8
  namespace :fixtures do
5
9
  desc 'Dumps all models into fixtures.'
6
10
  task :dump => :environment do
@@ -14,7 +18,7 @@ namespace :db do
14
18
  puts "Models: " + models.join(', ')
15
19
 
16
20
  models.each do |m|
17
- model = m.classify.constantize
21
+ model = m.tableize.classify.constantize
18
22
  create_fixture(model)
19
23
  create_fixture(model.version_class) if model.versioned?
20
24
  end
@@ -1,6 +1,6 @@
1
1
  class <%= migration_name %> < ActiveRecord::Migration
2
2
  def self.up
3
- create_versioned_table :<%= table_name %> do |t|
3
+ create_content_table :<%= table_name %> do |t|
4
4
  <% for attribute in attributes -%>
5
5
  <%=
6
6
  case attribute.type
@@ -31,6 +31,7 @@ class <%= migration_name %> < ActiveRecord::Migration
31
31
  def self.down
32
32
  ContentType.delete_all(['name = ?', '<%= class_name %>'])
33
33
  CategoryType.all(:conditions => ['name = ?', '<%= class_name.titleize %>']).each(&:destroy)
34
+ #If you aren't creating a versioned table, be sure to comment this out.
34
35
  drop_table :<%= table_name.singularize %>_versions
35
36
  drop_table :<%= table_name %>
36
37
  end
@@ -0,0 +1,57 @@
1
+ require File.join(File.dirname(__FILE__), '/../../test_helper')
2
+
3
+ class RouteBuilder
4
+ include Cms::Routes
5
+ end
6
+
7
+ class Bear < ActiveRecord::Base
8
+ acts_as_content_block
9
+ end
10
+
11
+ class Kindness < ActiveRecord::Base
12
+ acts_as_content_block
13
+ end
14
+
15
+ class RoutesTest < ActiveSupport::TestCase
16
+
17
+ test "Verify behavior of classify, and how it works with already pluralized symbols" do
18
+ assert_equal "Kindness", :kindnesses.to_s.classify, "routes will pass 'plural' symbols to 'content_block', rather than single"
19
+ end
20
+
21
+
22
+ test "behavior of 'content_blocks' route generator" do
23
+ rb = RouteBuilder.new
24
+
25
+ # Expect
26
+ rb.expects(:resources).with(:bears, {:member => {:publish => :put, :usages => :get, :versions => :get}})
27
+ rb.expects(:version_cms_bears).with("/cms/bears/:id/version/:version", :controller => "cms/bears", :action => "version", :conditions => {:method => :get})
28
+ rb.expects(:revert_to_cms_bears).with(
29
+ "/cms/bears/:id/revert_to/:version",
30
+ :controller => "cms/bears",
31
+ :action => "revert_to",
32
+ :conditions => {:method => :put})
33
+
34
+ rb.content_blocks :bears
35
+
36
+ # Verifies the exact messages being passed to the route generator
37
+ end
38
+
39
+ test "model names with s at the end behave identically (since content_blocks expects plural symbols)" do
40
+ rb = RouteBuilder.new
41
+
42
+ # Expect
43
+ rb.expects(:resources).with(:kindnesses, {:member => {:publish => :put, :usages => :get, :versions => :get}})
44
+ rb.expects(:version_cms_kindnesses).with("/cms/kindnesses/:id/version/:version", :controller => "cms/kindnesses", :action => "version", :conditions => {:method => :get})
45
+ rb.expects(:revert_to_cms_kindnesses).with(
46
+ "/cms/kindnesses/:id/revert_to/:version",
47
+ :controller => "cms/kindnesses",
48
+ :action => "revert_to",
49
+ :conditions => {:method => :put})
50
+
51
+ rb.content_blocks :kindnesses
52
+
53
+ # Verifies the exact messages being passed to the route generator
54
+ end
55
+
56
+
57
+ end