Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Decorate scoped associations #128

Closed
javierv opened this Issue · 7 comments

6 participants

@javierv

I've started experimenting with Draper, and looks great. Thanks!

I've just seen automatically decorate associations has been added, and it works great. For example, this works as expected:

unscoped_comments = PostDecorator.find(1).comments
unscoped_comments.map(&:some_comment_decorator_method)

However, it doesn't work if we use some scopes:

scoped_comments = PostDecorator.find(1).comments.order("created_at DESC")
scoped_comments.map(&:some_comment_decorator_method)

The reason apparently is:

unscoped_comments.class   => Draper::DecoratedEnumerableProxy
scoped_comments.class     => ActiveRecord::Relation

My feature request would be the second case to automatically work, although I don't know if that's out of the scope of this project.

Thanks!

@michaelfairley

I'm not sure there's a great way to do this (but hopefully I'm wrong).

Compare PostDecorator.find(1).comments.size and PostDecorator.find(1).comments.order("created_at DESC"). In once instance, we want draper to give you the result of calling the method on the decorated class, and in the other we want draper to re-decorate the result.

Draper would need a mechanism (decorates_scope :order perhaps) for it be told that all calls to order should be redecorated. And then it need to have that called on it for all ActiveRecord::Relation methods, and any custom scopes.

An option for how you can deal with this without waiting for a change to draper (this is roughly what the hypothetical decorates_scope would do):

# In CommentDecorator
def order(*args)
  self.class.decorate(model.order(*args))
end
@linuxonrails

I have the same problem: Decorator doesn't work 100% with associations.

PostDecorator.last.user.class
 => UserDecorator

@posts = PostDecorator.decorate(Post.public.lastest)
> @post.first.user.class
 => UserDecorator

But @posts.first.summary don't work (for example)

class UserDecorator < ApplicationDecorator
  decorates :user
  def name
    mode.username
  end
end

class PostDecorator < ApplicationDecorator
  decorates :post
  decorates_association :user

  def summary
    model.user.name # ERROR! mode.user is not an UserDecorator :-(
  end
end
@michaelfairley

@linuxonrails, if you do user.name instead of model.user.name, it should work. model is the underlying model, so it has no knowledge of any of the decorator related stuff.

@linuxonrails

Very thanks michaelfairley! It works!!!

@adamcrown

Also, calling scopes on the decorator class directly returns undecorated results.

class User < ActiveRecord::Base
  scope :admins, where(:admin => true)
end

class UserDecorator < ApplicationDecorator
  decorates :users
  decorates_association :admins
end

UserDecorator.admins.first.class #=> User

I'm assuming that this is because decorates_association is decorating instance methods but not class methods.

@rboyd rboyd referenced this issue from a commit in rboyd/draper
Robert Boyd decorate scoped associations #128 eb27430
@rboyd

I have a small one-liner patch to lib/draper/base.rb that would allow decorates_association to take a :scope option. Pull request for consideration to follow.

Contrived example: decorate a Company that has-many associated Employees and we'd like to order them by birthdate:

class CompanyDecorator < Draper::Base
  decorates_association :employees, scope: :by_birthdate
end

in Employee:
scope :by_birthdate, order('birthdate')
@steveklabnik

This should be closed by #223, right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.