Better Ruby Presenters

9 September 2011

My last blog post caused a bit of a stir in some circles. I got a bunch of emails. Apparently, I need to expand on a few things. So here we go. Let's rap about the Presenter pattern, shall we?

No seriously, helpers suck

In Ruby, everything is an object. Every bit of information and code can be given their own properties and actions. - ruby-lang.org/about

... except helpers. Why is it in Ruby that everything is an object, even integers, yet as soon as we need to format a date, we all turn into Dijkstra and bust out structured programming? Actually, come to think of it, Dijkstra wouldn't even write any code, because it's beneath him, but you get the idea. (if you don't get this, it's a joke. About proofs, telescopes, and CS...) Helpers are like a compliment that you don't want to give, but feel obligated to: "Yeah, I mean, well, you tried, and that's what counts, right?"

This is the topic of a future post, but when programming in a langauge, you want to work with its primary methods of abstraction. In Ruby, that's objects, and there's a good reason for that: functions don't provide a sufficient amount of power to tackle hard problems. I don't want to get into this either, but there's a reason that objects exist, and that nobody's making procedural languages anymore. No biggie. C has a special place in my heart.

But I digress: objects > functions. At least in the context of getting stuff done in Ruby. This pretty much applies to most of the rest of the points in this post, so just keep that in the back of your brain.

Why not a class method?

Well, first of all, class methods also suck. Here's the issue: Can you tell me the difference between these two methods?

def foo
  "hello"
end

class Bar
  def self.foo
    "hello"
  end
end

foo
Bar.foo

Yep, that's right. You can see it clearly from the last two lines: class methods are functions that happen to be namespaced. That means they're slightly better, but really, DictionaryPresenter.as_dictionary(something) might as well just be a helper. At least as_dictionary(something) is shorter.

Here's another reason: I didn't make that method be a class method, even though there was no state, because a really real presenter (I mean, that was a real world example, but...) generally works a little different. Usually, I make presenters that actually stand in for the objects they're presenting. Check this out. Here's the presenter I showed you:

class DictionaryPresenter
  def initialize(collection)
    @collection = collection
  end

  def as_dictionary
    dictionary = ('A'..'Z').inject({}) {|h, l| h[l] = []; h}

    @collection.each do |p|
      dictionary[p.title[0]] << p
    end

    dictionary
  end
end

The real-world presenter that I used this for looked like this:

class DictionaryPresenter
  include Enumerable

  def initialize(collection)
    @dictionary = ('A'..'Z').inject({}) {|h, l| h[l] = []; h}

    collection.each do |p|
      @dictionary[p.title[0]] << p
    end
  end

  def each &blk
    @dictionary.each &blk
  end
end

... or close to this. There was an 'other' category, and a few other things... but you get the idea. Now, instead of this:

@posts = DictionaryPresenter.new(Post.all).as_dictionary

You do this:

@posts = DictionaryPresenter.new(Post.all)

And the presenter actually stands in for the hash. A subtle but important difference. This gives you more options, because you have a real, live object instead of just some random processing. With this simplistic presenter, you might not see a huge benefit, but often, you'll want something a bit more complicated. And since this was what I had in my head, I didn't make as_dictionary be a static method.

Oh, and presenters that decorate a single object rather than a collection often implement method_missing, so that you only add methods rather than hide most of them. Some don't. It depends.

Blocks vs. Policy

I also showed off a Ruby version of a design pattern known as the Policy pattern, or sometimes the Strategy pattern. Turns out that Policy is often a bit heavyweight for Ruby, especially in an example like this, so I wanted to show you an alternate version of it, taking advantage of a Ruby feature: blocks.

For reference, the old code, put into the new code:

class DictionaryPresenter
  include Enumerable

  def initialize(policy, collection)
    @dictionary = ('A'..'Z').inject({}) {|h, l| h[l] = []; h}

    collection.each do |p|
      @dictionary[policy.category_for(p)] << p
    end
  end

  def each &blk
    @dictionary.each &blk
  end
end

class UserCategorizationPolicy
  def self.category_for(user)
    user.username[0]
  end
end

We could use blocks instead:

class DictionaryPresenter
  include Enumerable

  def initialize(collection, &blk)
    @dictionary = ('A'..'Z').inject({}) {|h, l| h[l] = []; h}

    collection.each do |p|
      @dictionary[blk.call(p)] << p
    end
  end

  def each &blk
    @dictionary.each &blk
  end
end

DictionaryPresenter.new(Post.all) do |item|
  item.title[0]
end

While this is shorter, and a bit more Rubyish, it also means that we lose the reification of our concept of a policy. While this is shorter, I find it more confusing. Why am I giving this one line block to the presenter? It's not really clear to me. And I can't give a better name to item... and if I want to change the policy, it has to be done in every place we use the presenter...

This does get to the root of another thing that will end up being a follow-up: What's the difference between closures and objects? If you don't know, maybe this will get you thinking:

#ugh, this is slightly odd, thanks Ruby!
def apply(proc=nil, &blk)
  if block_given?
    blk.call
  else
    proc.call
  end
end

proc = Proc.new do
  puts "a proc!"
end

class MyProc
  def call
    puts "an object!"
  end
end

my_proc = MyProc.new

apply do
  puts "a block!"
end

apply proc

apply my_proc

Chew on that a while.

This is too verbose

Absolutely. DictionaryPresenter.new(PostCategorizationPolicy, Post.all).as_dictionary is too long. 100% there. Good thing that I'd actually write this:

Dictionary.new(Post.all, ByTitle)

I switched the arguments around, because it reads better. When writing blog posts, you have to balance writing code samples that explain what you're trying to say, and ones that are 'real.' I tend to be a bit more verbose with things like this, because it's easier for someone who just jumps in to remember what all the parts are... then again, by not showing the 'real code,' people might end up implementing the crappy, verbose version. It's always a trade-off, and I may or may not make the right choice. It happens.

And yes, even earlier in this blog post: I said DictionaryPresenter and I'd really just say Dictionary.

Where does all of this go?

You've got two options, and only one of them is good: You should make a directory in app for your presenters. In this case, I'd be running touch app/presenters/dictionary.rb pretty quick. The other case is to put things in lib. This whole debacle uncovers something that @avdi went on a rant about over the last few days: models don't have to inherit from anything. Here's what Wikipedia says about models:

The model manages the behaviour and data of the application domain, responds to requests for information about its state (usually from the view), and responds to instructions to change state (usually from the controller). In event-driven systems, the model notifies observers (usually views) when the information changes so that they can react.

See anything about "saves stuff to the database?" Okay, 'manages... data' could be, but the point is, it's not required. Models are the reification of a concept that exists in your application domain. Persistance is not required for every concept.

Therefore, if it relates to your problem domain, it goes in app. If it doesn't, it goes in lib. Something like Dictionary? Depends on how important you think it is. It's probably pretty important; that's why you made it a class.

Design Patterns? Are you serious?

Yes. Design patterns don't suck, Design patterns in Java suck. I'm not even going to start this one here, expect more in this space soon.

Design patterns are great, and they're totally useful in Ruby.

In conclusion: A shout-out

I hope you've enjoyed this small digression on Presenters. If you're gonna use presenters in your application, I encourage you to write simple ones as simple Ruby classes, but if they get slightly more complicated, you need to check out Draper by my buddy Jeff Casimir. It lets you do stuff like this:

class ArticleDecorator < ApplicationDecorator
  decorates :article

  def author_name
    model.author.first_name + " " + model.author.last_name
  end
end

article = ArticleDecorator.find(1)
article.author_name

There's a lot of features to it, so check it out on GitHub. Totally worthwhile.