fat-code-refactoring-techniques
fat-code-refactoring-techniques copied to clipboard
RailsConf: Draper Decorators
RailsConf 2014 Talk, Tuesday, 2:30, Ballroom 4, Concerns, Decorators, Presenters, Service Objects, Helpers, Help Me Decide!
Draper Decorator
Code: Github Fat Code Refactoring Techniques Pull Request Draper
Example: Added Draper Decorator class MicropostDecorator. Method posted_ago dries up code in 2 views.
Why?
- You're putting presentation code in your model or model-concerns.
- You want to organize some helper methods by models.
- You've got logic in your controllers/views that is strictly related to one model, but multiple controllers/views.
- You need a good place to consolidate the creation of flash messages related to a given model.
To quote the Draper Readme:
Decorators are the ideal place to:
- format complex data for user display
- define commonly-used representations of an object, like a
namemethod that combinesfirst_nameandlast_nameattributes - mark up attributes with a little semantic HTML, like turning a
urlfield into a hyperlink
What?
- Draper is a popular gem that facilitates model decorators.
- Easy to use formula for introducing decorators in your application.
- Simple to include like Concerns.
- Widely used in the Rails community.
- drapergem/draper on github
- Railscasts Draper Episode
Steps
- Add
gem 'draper'= and run =bundle - Run Draper generator:
rails generate decorator User, which createsapp/decorators/user_decorator.rbandspec/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.decorateto get a decorated instance of the model.
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.