I created this refactoring example for my RailsConf 2014 talk on refactoring fat controllers.
Here is the code for this example:
https://github.com/justin808/fat-code-refactoring-techniques/pull/4
Please feel free to make comments in the PR or in this message thread. Thanks in advance for any feedback on this topic.
Draper Decorator
- Easy to use formula for introducing decorators in your application.
- Simple to include like Concerns.
- Widely used in the Rails community.
- Works for me!
- drapergem/draper on github
- Railscasts Draper Episode
Draper Steps
- Add
gem 'draper'= and run =bundle
- Run Draper generator:
rails generate decorator User
, which creates
app/decorators/user_decorator.rb
and
spec/decorators/user_decorator_spec.rb
. - Move presentation specific view code to decorator.
- Put
h.
in front of calls to helpers. - Remove references to the model in the decorator, as the method is
essentially on the model. - Call
model.decorate
to get a decorated instance of the model.
- Put
Draper Applicable Situations
- Extension to model that only applies to views and presentation.
- Calculations done in view using model object.
- Code in view helper that is more closely aligned with the model.
- Code is that seems relatively general as opposed to clearly useful in only
one view. - If method feels relatively generic for views, but specific for a given model,
then the decorator is a good place to put the method.
Draper Advantages
- Relatively simple way to add functionality to the model that only applies to the
connection of the model to the view. - Can separate presentation specific code from the model.
- Methods added to the model via the decorator have access to both view helper
methods as well as the model. - It’s super easy to automatically convert the retrieved model object into it’s
decorated instance, either manually or automatically, at the controller
layer. - Simple to find the decorator methods, such as using for verification in
feature specs.
Draper Disadvantages
- Shares similar problems with concerns in that the model object is still
getting fatter. - If there’s multiple methods needed for some complex logic, that should be
broken into it’s own PORO. - The advantage of ease of adding more methods can also be a disadvantage in
that the Decorator can turn into a junk-drawer of loosely coupled methods.