Upgrading to Refinery CMS 2.0
Posted by Craig Ambrose on March 04, 2012 at 10:58 PM
Refinery 2.0 is out, and I certainly think it’s the best option for doing content management in Rails at the moment. It’s rails 3.2 compliant, uses the asset pipeline, and it’s all built using engines in the rails way.
Since the last stable release (1.0.8) however, Refinery has changed so much that there is no longer an official or automated upgrade path. An upgrade is possible however, and I’ll run you through the steps below. Your Refinery 1.0 app will of course be running on rails 3.0, and so upgrading you application also involves an upgrade of Rails at the same time. This article will assume that you already have some knowledge about upgrading from rails 3.0 to 3.2, but if not you can read plenty of great articles on that. Be sure to read up on the asset pipeline if you haven’t used it before.
Before you start, I also suggest that you create a sample Refinery 2.0 application to use as a reference. Perhaps even give it the same name as your real application, to help minimize the differences between your sample app and your real one if you wish to compare them in a file comparison tool.
This guide covers the main Refinery CMS engines. It doesn’t cover other commonly used engines, not even Blog or Search. What I’ve done is disabled those engines (comment the gems out in your Gemfile) for the upgrade, and then they can be re-enabled after the migration is complete. Leave me lots of love in the comments if you want me to post upgrade guides for those other engines.
Also, I’m sure I don’t even need to mention, do this upgrade in a branch.
STEP 1: Migrate Data
Refinery 2.0 does not know how to migrate your Refinery 1.0 database. You’ll need to manually insert a migration into your application and run it before you upgrade anything. I’ve written a migration, so go grab it here (https://gist.github.com/1964785) and paste it into a migration file in your app, then run it.
STEP 2: Upgrade Gems
Upgrade you Gemfile to rails 3.2.1 and Refinery 2.0. Comment out any other refinery engines temporarily.
STEP 3: Rails update
Perform the normal Rails 3.2 upgrade steps
- Upgrade to a recent version of mysql2 if using an old mysql gem.
- rake rails:update
- Create assets dir, and move application images, stylesheets, javascripts
STEP 4: Upgrade refinery generated files
Run the refinery generator. This is normally done on a new app, but like rails:update will ask if you want to overwrite files. You’ll need to go through them one-by-one.
rails generate refinery:cms
In particular I found I had to ensure that I replaced:
Refinery.rescue_not_found = false
with
Refinery::Core.rescue_not_found = false
STEP 5: Refresh cookies
Refresh your browser cookies. This is necessary if you have run the old version of the site in that browser. I imagine that this might also cause problems in a production deploy for users who still have their browser open.
STEP 6: Change partial paths
If you have overridden your application layout, you may have partial tags like like:
<%= render :partial => “/shared/html_tag” %>
Change to something like the following:
<%= render ‘/refinery/html_tag’ %>
You many need to consult the application layout template inside refinery.
STEP 7: Move settings into config files
Move settings out of database. Settings now go in initializer files. Copy the entire config/initializers/refinery directory out of a sample refinery 2.0 app into your application, and go through and fill out the settings. Use the settings table in your database as a guide, but some settings have changed, so read the new initializer files right through.
STEP 8: Move overridden Refinery templates
For any templates you have overridden, they are probably now in the wrong paths. In particular, most are namespaced inside a refinery folder now. Consult the refiney codebase to find the new location of the overridden template. For example, /layouts/_header is now /refinery/header. Simply move the file in your application into a folder called “refinery” in your views folder.
STEP 9: Change custom template code
In your custom templates, you will need to update any code calling now invalid refinery APIs. In particular, calls to settings will now be invalid. For example, replace:
RefinerySetting.find_or_set(:site_name, “Company Name”)
with
Refinery::Core.site_name
Likewise, all refinery routes are now namespaced. Replace root_path with refinery.root_path.
STEP 10: Create page slugs.
Refinery now uses friendly ID. These “slugs” are created for each page object on save. Create slugs for all pages by re-saving them all. Refinery::Page.all.map(&:save)
STEP 11: Profit!
You should be good to go now. Let me know how it went. :)
Building Rails Apps from Bigger Blocks
Posted by Craig Ambrose on May 04, 2011 at 12:05 AM
With rails, we build up our application using the chunks of functionality that the framework and it’s libraries provide. This is different to web platforms like Drupal, where we might reasonable expect to get a basically working application (for the default use cases) out of the box, and be able to configure it to change it slightly.
The problem with configuring a monolithic platform is of course that we’ll never get it to work exactly the way we want. That approach works well if our requirements are close to it’s area of core functionality, but for custom software, we want to build up, rather than configure downward.
Building our apps up has been a key philosophy in rails from the beginning. In fact, it’s been so important that the core team has strongly resisted any changes to rails which looked too much like they encouraged monolithic, configurable software.
So, if we think of a rails app as a structure built up from lots of little blocks, which all do different things and are often interchangeable, then we have a good working metaphor for the ideal rails development process. Rails 3 (due to the Merb influence) has done a lot of work to ensure that some of the fundamental building blocks of rails are easily swappable. This blocks, like which ORM to use, form the foundations of the awesome block fortress that we want to build.
With each layer of blocks that we build up, the blocks tend to be somewhat dependent on the interface of the blocks below. For example, we might build a login system that requires a user model that basically behaves like an ActiveModel object, although we don’t care if it’s implemented using ActiveRecord, DataMapper, or something else.
Once the tower of blocks rises above the foundation of the Rails framework itself, then adding more blocks becomes dependent on some sort of agreement on those interfaces. This tends to happen when gems or plugins become so commonly used that supporting them, or something that looks a bit like them, is a natural approach for further libraries.
For example, there are a number of libraries supporting user authentication, and most of them expose a current_user method which returns some sort of user object. Although this is far from being a clearly defined interface, it’s almost all you need for other libraries to do things conditional on being logged in.
As we reach a consensus on certain libraries being good ones, even the ones that follow them tend to implement these core bits of interface. For example, you’ll find that changing an app from using Authlogic to using Devise is fairly simple.
This process made it feel a bit like the blocks were slowly getting bigger, and we could build bigger and bigger towers out of them without needing to write our own code from scratch. Certain parts of our app are good candidates for giving a lot of thought and custom code, but other parts are simply the bolt-ons that we need to get there, and it’s great to be able to use a generic implementation without having to re-invent the wheel. We don’t rewrite paperclip when we want to store images, and most people tend to use an authentication system these days.
So, why did the progression of these bigger and bigger blocks stop? Where are the rest?
If we want to be able to build up, rather than configure down, from any level of detail, then we need blocks at each level of detail. We need something to store files (paperclip), something to upload and store files (which uses the previous), something to provide an image gallery (which uses the previous), etc. It’s up to us which areas of our app use large blocks, and which ones use small ones.
When we start to talk about blocks that are large chunks of our application, they start needing to include user interface. This tends to be where we get scared and run away. The tricky bit here is the lack of defined interface, and that’s why you tend to see entire open source rails apps that do useful things like run a blog, forum, image gallery, social profiles, but not so many rails plugins that do these, and even less rails plugins that do it by building the functionality up from even smaller blocks which you can swap out.
In my next post, I’ll lay out some examples of what these “slightly larger that presently available” blocks of code might be, and take a stab at figuring out how we might start to define interfaces for them, while keeping a decentralized community process.
Quick and Easy ruby quality thresholds
Posted by Craig Ambrose on April 14, 2010 at 10:25 PM
Ruby on Rails’ opinionated attitude towards testing has introduced a lot of people to test driven development. Whether it’s because rails development has encouraged good testing practices, or because it has attracted pro-testing developers, rails (and ruby in general) now has a large ecosystem of testing and quality tools.
If you’re a rails developer, you’re probably already writing tests. You’re probably using RSpec or Shoulda (and also Cucumber, but I’m just talking about unit tests here). You’ve probably run your code through rcov, to see how well much code your tests cover, and you’ve probably also looked at other code quality metrics, like the ones generated by metric_fu (or a hosted service like codeyak).
Quality metrics for your code force you to write good code. They are an essential part of test-driven development, because in TDD our design is supposed to be driven by spotting code smells. Unless we think we can get the design (both in the macro and micro) correct first time (and we can’t), then we always have to be on the lookout for these code smells that will drive us to refactor and evolve the design into something better. Since I’m using words like “drive” and “force”, obviously I intend these metrics to be enforced. If you aren’t already doing it, start now.
The following example presumes that you’re testing with rspec, but it only requires slight modifications to make the rcov threshold work with other testing libraries.
First up, ensure that your app has the following gems installed (bundled):
metric_fu, flay, flog, reek, roodi, rspec, rcov
Then, grab my continuous integration rake tasks from here:
Finally, tell your continuous integration server to run “rake ci”. I use cruise_control.rb, but there are plenty to choose from.
You can modify the hash values in the THRESHOLDS constant to set the quality thresholds for your project. Set them so that they just pass at the moment, and then try to improve the code and slowly crank them tighter. For rcov that means raising it (towards 100.0), and for the others, that means lowering them.
Since you’re using metric_fu, you’ll also get graphs and pretty reports of the output. If you’re using cruise_control.rb, look for the “output” link in your build artifacts on the web interface. I’m not executing rcov via metric_fu in my code, because the metric_fu rcov task hides errors in the specs, and we also want the build to fail if a spec fails.
Thumbnailing to a fixed size without stretching using attachment_fu
Posted by Craig Ambrose on May 10, 2009 at 09:54 PM
I was going to write a blog post congratulating myself on being clever for writing a little extension to the attachment_fu plugin that allowed Procs to be used as thumbnail geometry strings, thus allowing you to write custom resizing code. This was all so that I could get it to perform a resize that worked exactly as I wanted, to give me a thumbnail of fixed dimensions which scaled and cropped but never stretched the image.
Before I did so, I thought I’d better just check that attachment_fu hadn’t changed recently to make my extension not work. I take a peek at github and lo and behold, Rick and other committers have been busy beavers on attachment_fu this year, and in fact another kiwi has already added the functionality that I need.
You can find David Jones’ post on how his cropping functionality works here, although it is describing his old patch for acts_as_attachment, and with attachment_fu it’s used slightly differently, as described below.
Lets say that your users are uploading photos to your site, in a range of aspect ratios (including common landscape and portrait photos). Cropping to a square thumbnail is a problem already discussed on this blog, but what if we want to crop to fixed size that isn’t square?
Image magic geometry strings, when passed to the resize function, do not force the image to become that size if the aspect ratio doesn’t match. For example, if I specify a size of “100×75”, then an image already in a 4:3 aspect ratio will scale just fine, but a portrait image in the opposite ratio will end up 75 pixels tall as desired, but only 19 pixels wide, in order to preserve it’s aspect ratio. If instead I force the new image size, using the geometry string “100×75!”, I will get an image of the correct size, but it will be stretched and distorted.
It goes without saying that we never want to stretch. Some people like to stick with the behaviour of the first example, and simply fill the missing sections of the image with a background colour. The other option, which I prefer, is to crop the image in the dimension that doesn’t fit into the new aspect ratio. The goal is to get an image of exactly my desired dimensions, which is scaled to maintain aspect ratio, and then cropped as little as possible.
Doing this with the latest version of attachment_fu from github is as easy as specifying the geometry string “100×75c”. The “c” at the end is used to indicate that we want to use the cropping algorithm. It’s not a normal part of an image magick geometry string and it does get removed by attachment_fu when it decided what algorithm to use.
If this is not quite what you need, you might also want to check out what the “e” option does.
PluginInstances - A different way to use rails plugins
Posted by Craig Ambrose on March 18, 2009 at 10:19 PM
I’ve just released the PluginInstances pluging at:
http://github.com/craigambrose/plugin_instances/
This plugin allows you to have individual route sets for other plugins, including a unique instance id.
Without using this plugin you can specify a routes.rb in your plugins (as of rails 2.3), and these routes are merged into the global route set used when determining how to process the current request. This is great for allowing a plugin to introduce a set of functionality which exists only once on the site (like a login system).
The PluginInstances plugin is designed to enable individual instances of plugins to be placed in different places on the site. For example, lets say that your site is content managed, and has tabs across the top which link to various types of functionality:
In your application’s routes.rb file:
map.plugin_instances "/tabs/:id"When a request is detected with a path like ”/tabs/23/admin”, it realises that this matches the plugin_instances route, finds the relevant instance (eg: PluginInstance.find(23)), asks that instance what plugin it represents (eg: a forum, user profile, etc), and then passes the route ”/admin” to the route set for that plugin, along with the plugin instance object. Thus, a forum plugin could be written which can be instantiated at different places in the site, and just has to scope itself using the plugin instance id.
For detailed usage instructions, see the README file displayed at the github project page .
I’m using this plugin at present to build a pluggable wiki, where each new page that you create could be just a simple page of versioned text (like a regular wiki), or it could be a calendar, a forum, etc. People using drupal will also find this sort of routing system familiar, so I’m sure there are plenty of other useful applications for it.

