Skip to main content

Decorators From Scratch Discussion

General • Asked by Chris Oliver

Nailed it. Thanks again Chris - could never find a good explanation on Decorators, hence I never used them, will be sure to use them now!

That's awesome to hear. Thanks Nick! :)


Thanks, Chris, helpful as always! You also can use SimpleDelegator to handle the ActiveRecord (and delegation) issues. Here's an example https://hashrocket.com/blog...

That's pretty neat. I know I've seen SimpleDelegator mentioned before in but never looked into it. I'll have to fiddle with it now!🤘

Yea I learned of the technique in this context from Noel Rappin's book, Rails 4 Test Prescriptions (which is a great book, link here: https://www.amazon.com/Rail.... He uses it for presenters, which I've used and liked.


mmm... looks like a lot of dependency and complexity to keep a eye for.


When should use decorators VS helpers?


Great episode Chris! Definitely going to be using this. One thing I'm curious about, I often use partials to render collections instead of iterating through them in the view, e.g. render @users instead of @users.each do |user|... How would this work (or would it work) with the decorated user objects? I suppose you would just need to specify the partial name and local variables instead of relying on the rails shorthand of render @users right?

Whoops, I had this tab open to reply to at some point...9 days later. :P

Yeah, you'd probably need to pass the partial name in to pass over the presenters that way. I'm sure there's some way you could override some things in the presenter trick Rails into rendering the proper partial name automatically. The draper gem might be able to do that and have some insights on how to pull that off with your own implementation. I know that they have a Relation-esque collection object that might be what you'd need to add to your own implementation from scratch to do that.


Thanks. Great Episode !
I have one remark though: Is it really a good idea to use the view context in the decorator, for creating things like html tags ? Doesn't this create a coupling of the decorator with the view format? I mean you this way, you will need a different decorator for xml or json views (which do not use content_tag helpers etc...)

That's a great question. If you need to build decorators that work in both cases, then yes, you'd want to do one of two things:

1. Separate decorators for JSON and HTML and wrap them accordingly depending on the response type. Downside to this is more decorators.
2. Build generic decorators and leave it up to your views. Downside to this is that part of the benefit of having the link_to's and etc in the decorator is that your view can remove logic entirely. That's probably not possible if you're not able to write logic in the decorator.


Hi Chris, if we are using Rails 4+, we don't actually need to modify the `auto_load_paths` anymore, as:

> All subdirectories of app in the application and engines present at boot time. For example, app/controllers. They do not need to be the default ones, any custom directories like app/workers belong automatically to autoload_paths
> http://guides.rubyonrails.o...

I thought that was the case! It didn't work for me the first time I tried it, but it could have been spring caching things or something. Thanks for sharing that. :D


Awesome episode! One thought on collections of presenters. I found it annoying to keep writing out the collection.map { |object| ObjectPresenter.new(object) } syntax every time.

In my situation I use a BasePresenter that all my other presenters inherit from. I then add a class method "collection(...)" that allows me to create a collection of presenters with cleaner syntax.

The above syntax now looks like this:

@objects = ObjectPresenter.collection(Object.all, view_context)

class BasePresenter < SimpleDelegator
def self.collection(objects, view = nil)
objects.map { |object| new(object, view) }
end

def initialize(object, view = nil)
@object = object
@view = (view || ActionController::Base.helpers)
super(@object)
end
end


Found this very useful, thank you! If you have any more patterns wisdom, please bring it on :)


Amazing episode! I guess this kind of decorators are different to the decorators in the GoF book. Those inherit from the class they decorate to adhere the Liskov's substitution principle. I suppose this can't be done because active record naming conventions would not be compatible with this.


What exactly is view_context? Also what exactly is happening in config.autoload and why do we have to create a module in the application.rb ? is a decorator just a class that wraps around a model or something to extend its functionality in a well-encapsulated manner so that the scope of itis separate and gives us a way to separate the concerns of an application more?


Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 22,346+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.