fat-code-refactoring-techniques
fat-code-refactoring-techniques copied to clipboard
Earlier Draft: Draper Decorators
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 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.
Another downside is the way a developer have access to the presenter: @model.decorate vs UserDecorator.new(@user). It adds another responsibility to AR models: they are aware of the decoration logic.
That #decorate API is an handy solution do a bigger problem: the lack of separation between views and templates in Rails. A View, should be the place where to initialize a decorator and then the template can use it <%= decorator.formatted_followers_count %>.