Upgrading a BrowserCMS project to 4.0

peakpg edited this page Feb 5, 2014 · 15 revisions
Clone this wiki locally


Projects must first be upgrade to 3.5.4 or later. Owing to how migrations are handled, its isn't possible to upgrade directly to 4.0.

(Note: Work in progress)


  1. Create a directory called config/broken_initializers. During the upgrade, move any initializers that throw errors from config/initializers to this directory temporarily.
  2. Remove or change emails for users with duplicate emails. 400 will enforce uniqueness so this must be done prior to upgrading.
select count(*) as emailcount, email from users group by email order by emailcount desc;


1. Update the Gemfile

Use the correct version of BrowserCMS, remove any version # references to Rails and Rails related dependencies (i.e. sass-rails, coffee-rails, etc)

gem "browsercms", "4.0.0.alpha"
# gem "rails", "3.2.5" # Use BrowserCMS dependency.
gem 'sass-rails' #, '~> 3.2.3' 
gem 'uglifier', #, '~> 3.2.2'

You may want to comment out all existing BrowserCMS modules initially, since they may not have CMS 4.0 versions availalble yet Then run bundle update.

2. Add migrations

  1. Record the timestamp for the existing 3_0_0 migration (i.e. 20080815014337).
  2. Delete all the BrowserCMS migrations (3_0_0, 314, etc) from the project.
  3. Add the migrations by running rake cms:install:migrations
  4. Rename the newly generated browsercms300.cms.rb so so it matches the old timestamp of browsercms3_0_0. This will prevent the new migration from running.

Then run rake db:migrate, then start debugging:

3. Debugging

Running rake db:migrate is likely to expose a number of errors related to Rails 4, BrowserCMS 4 or issues with modules. The steps to be taken for each project are different, but here are some possible resoluations:

  1. Issue: An initializer throws an error. Resolution: Move that file to config/broken_initializers. Carry on.
  2. Issue: Application.rb throws an error. Resolution: Comment out that block off code with an @upgrade tag so you can find it later. Carry on.
  3. Issue: Error: attr_accessible is extracted out of Rails into a gem. Resolution: Remove attr_accessible calls in models.
  4. Issue: uninitialized constant Cms::SomeModelName from routes.rb Resolution: See 'Namespacing Application Models below'
  5. Issue: Rails 4 error for using 'match' without a constraint: Resolution: See 'Rails 4 Routing' below

4. Namespacing Application Models

Edit your config/routes.rb to put all custom blocks under the application namespace. For example, for a project named 'Petstore' here's how it should look:

# Old
namespace :cms do content_blocks :events end
namespace :cms do content_blocks :people end

# New
namespace :petstore do 
  content_blocks :events
  content_blocks :people

Comment out any module engines that are not yet upgraded:

# mount BcmsNews::Engine => '/bcms_news'

5. Rails 4 Routing

5a. Using 'get' and 'post' rather than 'match'.

Do a find and replace for 'match' with 'get' in routes.rb. Change actions like:

match 'search' => 'search#new', :via => :post


post 'search' => 'search#new'

6. Devise

Create a file named config/initializers/devise.rb with the following in it:

Devise.setup do |config|

  # config.secret_key = ''


Devise will generate an error with a new secret_key. Add that the above file.

7. Modules/Content Types

Remove all references that look like these in existing migrations. They are no longer necessary.

Cms::ContentType.create!(:name => "Event", :group_name => "Events")

Create directories under app/models with the name of your application. (i.e. app/models/petstore). Then update all content block models to the following (based on the name of your Application):

module Petstore
  class Event < ActiveRecord::Base
    content_module :events

Rename the app/controllers/cms directory to match the name of the application (i.e. app/controllers/petstore). Then update each content block controller like so:

class Petstore::EventsController < Cms::ContentBlockController


Rename the app/views/cms directory to match the name of the application (i.e. app/views/petstore). Update the all the _form.html.erbs for both portlets/content types to use the new SimpleForm syntax.


<%= f.cms_text_field :name %>
<%= f.cms_check_box :is_online, :instructions=>"If the event is online." %>
<%= f.cms_text_field :url, :instructions=>"URL for the event registration." %>
<%= f.cms_text_editor :content %>
<%= f.cms_date_picker :comment_end_date, :label=> "Comment End Date", :instructions=>"(Optional) Use past date to prevent commenting, will default to one month in the future."%>
<%= f.cms_file_field :file, :label => "A PDF file" %>
<%= f.cms_drop_down :event_type, ["Webinar", "Meetup", "Continuing Education"], :label=>"Type" %>
<%= f.cms_template_editor :template %>


<%= f.input :name, as: :name %>
<%= f.input :is_online, hint: "If the event is online.", as: :boolean %>
<%= f.input :url, hint: "URL for the event registration.", as: :string %>
<%= f.input :content, as: :text_editor %>
<%= f.input :comment_end_date, label: "Comment End Date", hint: "(Optional) Use past date to prevent commenting, will default to one month in the future."%>
<%= f.input :file, label: "A PDF file" %>
<%= f.input :event_type, collection: ["Webinar", "Meetup", "Continuing Education"], label: "Type", as: :select %>
<%= f.input :template, :as => :template_editor %>