-
Notifications
You must be signed in to change notification settings - Fork 526
Upgrading to 1.0
A lot has changed in Draper 1.0, both under the hood and in the API. You can check out the change log or the compare view to see the extent of the changes, but if you just want to get up and running, here's a quick guide to how to upgrade from Draper 0.x.
You'll need to update your decorators' superclass (don't forget that you can have an ApplicationDecorator
and inherit from that!).
You might not have been inheriting from this class yourself, but doing so is a great way to add methods to your decorated collections (e.g. for pagination).
It's included by default into ActiveRecord::Base
and Mongoid::Document
, so if your models inherit from one of those, you're already set. If you want to decorate plain old Ruby objects, you should include this module manually to get a decorate
instance method.
To regain this behavior you need to add delegate_all
to the top of your decorator. Newly-generated decorators will have this by default.
If you were previously controlling which methods were delegated using allows
, denies
, or denies_all
, these methods have now been removed. Now, to control delegation don't add the delegate_all
. For denies_all
-style behavior, that's it, you're done!
To bring some delegation back into play, you can use the standard Module.delegate
from Active Support. We've overridden it to make to: :source
the default, so you can just write delegate :foo, :bar
where you might have had allows :foo, :bar
. Unfortunately, if you were using denies
, you're out of luck (unless you override method_missing
yourself) - try switching to a whitelist approach instead.
delegate_all
will also try to send missing class methods to the model class. If you follow the naming convention of SomeModelDecorator
decorating SomeModel
, Draper infers the model class from the decorator class and you don't need to put decorates :some_model
at the top any more. If you don't follow this convention, you'll still need the decorates
if you want the class methods to be delegated.
Previously, when you did ProductDecorator.decorate(Product.all)
, Draper guessed that what you actually wanted was a collection of ProductDecorator
s. Now, you need to tell it explicitly by doing ProductDecorator.decorate_collection(Product.all)
.
Note that for Active Record queries you can do Product.where(color: "red").decorate
instead. However, in Rails 3 all
returns an array, not a query, so Product.all.decorate
won't work (but you can instead do Product.scoped.decorate
).
Without the collection-decorating magic, Decorator.decorate
is now a simple alias for Decorator.new
. Even more tersely, though, you can use the decorate
instance method on models - Product.find(params[:id]).decorate
.
Draper no longer decorates ProductDecorator.find(id)
and other finder methods out of the box. Other methods of decorating found objects (e.g. Product.find(id).decorate
) should be preferred, but if you want to get this functionality back you can add decorates_finders
to your decorator definition.
A ProductDecorator
used to magically get a product
method that returned the underlying model. That isn't generated any more - it's now just called source
(and aliased to model
). You can get your product
method back by adding an alias_method :product, :source
.
Decorators are now fussy about the options you give them. In 0.18 you could save extra contextual information by doing Decorator.decorate(model, role: "admin")
and then accessing it through the saved options
hash.
In 1.0 you should use the :context
option: Decorator.decorate(model, context: {role: "admin"})
. The hash is then available through the context
method, as you might expect.