Representers

The Bad, The Ugly and The Worst

class PostRepresenter
  def represent(post)
    {
      id: post.id,
      title: post.title,
      comments: post.comments.order(created_at: :desc).map {
        |c| CommentRepresenter.new.represent(c)
      }
    }
  end
end
class PostsRepresenter
  def represent(posts)
    posts.map { |p| PostRepresenter.new.represent(p) }
  end
end

Can you notice the problem?

git commit -am "Fiksik"

class PostsRepresenter
  def represent(posts)
    posts.includes(:comments).map {
      |p| PostRepresenter.new.represent(p)
    }
  end
end
class MessageRepresenter
  def represent(message, user)
    {
      title: message.title,
      author_name: author_name(message, user)
    }
  end

  def author_name(message, user)
    # Complex logic required
    if author_visible?(message, user)
      message.author.name
    else
      "Placeholder"
    end
  end
end
class Superuser::MessageRepresenter
  def represent(message)
    {
      title: message.title,
      author_name: message.author_name
    }
  end
end
class PageRepresenter
  def initialize
    @redis = Redis.new
  end

  def represent(page)
    {
      views: MagicCounter.new(page, @redis).unique_since(10.days.ago)
    }
  end
end
class PagesRepresenter
  def represent(pages)
    pages.map { |page| PageRepresenter.new.represent(page) }
  end
end

What possibly could go wrong?

Query less

You should not do any DB queries in representers

The most important thing to me is that Representer shouldn't represent your database structure but it should return appropriate set of data for your endpoint

© by @jcieslar_

Related: AR vs PORO Entities, How to do REST

Logic less

Like templates representers should be dumb

Just do simple transformation

Knowledge less

Output and input format it's the whole world

If you really need any dependencies - inject them

Bonus

What's wrong with this code?

class SomethingRepresenter
  def represent(something)
    {
      foo: something.foo,
      bar: something.bar
    }
  end
end

The Representer

Decorator

design pattern that allows behavior to be added to an individual object without affecting the behavior of other objects from the same class

Wikipedia

The Representer

Subtype of decorator pattern which adds behavior for object transformation into different format

Homemade definition

class SomethingRepresenter < DelegateClass(Something)
  def to_json
    to_hash.to_json
  end

  def to_hash
    {
      foo: foo,
      bar: bar
    }
  end

  # TODO: to_xml, to_whatever
end
class SomethingRepresenter < Representable::Decorator
  include Representable::JSON

  property :foo
  property :bar
end

SomethingRepresenter.new(something).to_json

Representers

By Jan Dudulski

Representers

  • 137