A developer's journey through BrowserCms.

Tuesday, June 4, 2013

Adding a custom route engine

When customizing BrowserCms, I have found it useful to separate core BrowserCms code from my own. Namespacing is a great way to accomplish that. I like grouping my custom content blocks in related sections and not simply adding yet another content block to the 'cms' namespace.



Note: the last diagram in the attachment is from the browsercms code (I forked the github repo to include this change). The other diagrams are from a BrowserCms app instance.

See the detailed diagrams for more information.

The 'block_path' route view helper

‘block_path’ is an interesting beast.  It looks like a typical view helper (i.e., _path, _url), but it introspects the content block object and creates an array of objects and values that will be used by ‘link_to’ to generate a path.  (For more details on this style of route specification, see Creating Paths and URLs From Objects, section '2.8 Creating Paths and URLs From Objects')



The engine can be the default cms engine that comes with BrowserCms, the vanilla Rails engine, or another custom engine.

The action parameter is filled with special bcms actions, like ‘:versions’.

Then using the block, objects are extracted and included in the path; these objects will be translated into keys values for tables (this is nothing new).

Resolving undefined method 'cms_number_field'

After creating a custom content block for BrowserCms, if you had specified any 'integer' type in your generate command, you might see something like this when you go to create an instance of that content:

NAMESPACE=bcms_my401k ./bin/rails g cms:content_block BcmsMy401k::Widget user_id:integer name:string description:text
For some reason, when generating content blocks, integers are mapped to ‘cms_number_field’ form helpers, but they don’t seem to exist.

To resolve this issue, we simply need to provide the missing components that BrowserCms is complaining about.
  1. include 'number_field' in the list of form helper methods generated at load time
  2. associate a partial with the new form helper


Although this solution (creating a partial) is currently identical to ‘cms_text_field’, the partial could be updated later to validate a numeric entry.

Down migration issues with custom content blocks

While running down migrations that were created as a result from generating a custom content block type, 'def change' doesn't seem to be creating a 'down' migration. Perhaps it doesn't know what to do with the call to 'create_content_table'. I am hopeful that is the problem and not something with the latest ActiveRecord code.

In any case, when a migration is complex enough that it does not know how to create a 'down' migration from the 'up' syntax in the 'def change' method block, it is required to revert back to the old style, specifying 'def self.up' and 'def self.down' method blocks:

Thursday, May 30, 2013

Resolving issue with custom content blocks and version listings

BrowserCms provides generators that can be used to create custom content blocks.  This means that you can create models that inherit all the other niceties that come packaged with BrowserCms, like version control, including in pages, etc.

One hiccup I discovered was that the wrong routes were being used for any custom content blocks, even those that come from the sanctioned bcms_blog plugin.

To duplicate the issue,
  1. navigate to the cms content library: http://localhost/cms/content_library
  2. select one of the custom content block category types (e.g., Blog, if you have the bcms_blog plugin installed)
  3. create new content and edit and publish it several times
  4. list the entries (e.g., Blog > Blog Post)
  5. click on the entry that you edited
  6. click on 'List Versions'
  7. click on one of the versions
  8. click on 'View Content'
You are rewarded with a HTTP 404 warning:


Why is the page not found?  Take a look at the route.  It suggests that the resource be found under the 'cms' namespace.  That seems to be the problem; the bcms_blog uses its own namespace (bcms_blog) to avoid route conflicts.  So what's responsible for putting 'cms' in the view links.  The correct namespaces are used up until 'List Versions' is clicked and the page is refreshed.

I tracked down the issue with the JavaScript to the app/views/cms/blocks/versions.html.erb view.  The existing code was assuming that all custom content blocks use the 'cms' namespace.  This may not be the case, as with the bcms_blog plugin that has it's own Rails::Engine and, consequently, it's own route namespace.

By introducing some logic in the view's JavaScript, we can dynamically determine what namespace should be applied:

And the code to determine 'cmd_namespace'...

There are certainly more elegant solutions, but here is my short term solution with an idea of how to solve it better.

Wednesday, May 8, 2013

Create a new content_block type

I have really enjoyed using BrowserCms for my content management Rails applications. Besides coming packaged with a lot of great features from the get-go, it is quite accommodating for personalizing the user's experience while still tapping into BrowserCms's great features. For example, content_block models have features such as security, version control, and WYSISYG form elements. When it is required to add models to your app, to gain access to those features, one easy method is to use the BrowserCms's content_block generator. Of course, BrowserCms does have documentation for this process, but I wanted to have greater control over the namespace for the generated elements. I had to make some changes to the BrowserCms generator, and was successful.

Create a new content_block type for a BrowserCms application in a specified namespace.

Note: the original browsercms generator for content_block was altered ever so slightly. This example depends on the changes made in my forked copy of browsercms.

Friday, April 5, 2013

CKEditor instances and Ajax

I spent a little time trying to figure out how to manage the CKEditors on an authoring page. For the bulk of my solution, I give credit to StackOverflow. As noted in the example below, I did need to comment out the line with CKEDITOR.replace(instance); to get things working on my end.

If I understand this issue correctly, because I am using Ajax, the instances remain in memory. As I navigate to each page in my wizard, Ajax is used to get a fresh copy of the page partial. Each time the editor page is requested, the id values for the CKEditor instances is slightly different. CKEDITOR.instances lists registered editors that have been loaded. Those instances need to be cleared out in order to successfully load the new CKEditor instances.

I created a new helper method to generate CKEditor without the option to switch to plain text. Here is the template:

Here is the form helper: