Rails offers an easy way to render objects in a view that are automatically associated with their
own partials. With ActiveModel::Conversion, you can quickly build widgets out of classes (models or presenters or other).
In a recent project, we had several little status/info blocks that we wanted to render on a page. Each block required different model data. In the controller, as we started writing code to fetch all the right data and put it together, we quickly realized that things were going to get ugly. We started with something like this:
You can see that as we added more items to put on the page, both the controller and view got bigger and more complex.
What we wanted was two-fold:
- Reduce the amount of work done by the controller to prepare data for the views
- Build an easy way to render the different chunks of data as separate widgets
The first step is to build some presenters. Following from the above example, we write two simple wrappers (presenters) to nicely prepare our data so it’s easy to access and render by a view.
At this point, we can simplify the way the controller fetches the data by leveraging these presenters
This solves the first issue, but it has not simplified the view. This is where
ActiveModel::Conversion comes in.
ActiveModel::Conversion into our presenter classes, they suddenly know how to render themselves.
In both classes, we add:
This adds the following methods:
#to_partial_path to our classes. These methods are used by
ActionController::Base#render. We can now render the object directly like so:
Rails is effectively doing this:
render @object.to_partial_path, :<model name> => @object
to_partial_path generates a path that looks like
<model names>/_<model name>
Now that we’ve added the mixin, we can update the view:
And to finish it up, we need to add view partials (whose path is going to match
to_partial_path‘s response) for each of the presenter classes.
Now that we’ve got this far, we can do one more refactor:
At this point, the home page will render the two blocks, one showing hot stuff, and one showing recent activity. The partials are (for this example) pretty dumb, but you can imagine fleshing them out to pull from other methods that the presenters could offer.
- Using presenters is a simple way to compartmentalize logic that prepares model data for a view. That logic could be combining data from separate Rails models, or simple sorting, formatting or otherwise organizing the model data so that it is more easily accessible to the view in the way the view needs it.
ActiveModel::Conversion, the view can be directly tied to a presenter allowing it to act more like a widget that is easily rendered in your application views.
Sample Application – Widgetize Me!
I wrote up a quick sample app that shows off this technique. The main page simply pulls a random set of widgets and renders them. The widgets include
and each one is basically a simple model and a view partial.
Easily render a ruby class in Rails using
- Given a ruby class
- create the view partial in
- load it up in a controller
@widget = SuperWidget.new
- render it in a view