Skip to content
cavalle edited this page Dec 23, 2012 · 13 revisions

a.k.a. Decorators / View objects / View models

Version #1

http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/

class DonutChart
  def initialize(snapshot)
    @snapshot = snapshot
  end

  def cache_key
    @snapshot.id.to_s
  end

  def data
    # pull data from @snapshot and turn it into a JSON structure
  end
end

Version #2

# app/models/user.rb
class User < ActiveRecord::Base
  # first_name:string last_name:string website:string
end
# app/decorators/user_decorator.rb
module UserDecorator
  def full_name
    "#{first_name} #{last_name}"
  end

  def link
    link_to full_name, website
  end
end
# app/controllers/users_controller.rb
class UsersController < ApplicationController
  def index
    @users = User.all
  end
end
<%# app/views/users/index.html.erb %>
<% @users.each do |user| %>
  <%= user.link %><br>
<% end %>

Version #3

class AuthorSummary
  def initialize(author)
    @author = author
  end

  def published_count
    @author.posts.published.count +
    @author.videos.published.count
  end

  def draft_count
    @author.posts.unpublished.count +
    @author.videos.unpublished.count
  end

  def approval_count
    if @author.admin?
      @author.organization.posts.unapproved.count
    else
      0
    end
  end
end
<% summary = AuthorSummary.new(current_user) %>

Version #4

class PostSerializer
  def initialize(post, user)
    @post, @user = post, user
  end

  def to_json
    if @user && @user.admin?
      full_detail
    else
      summary
    end
  end

  def full_detail
    summary.merge({ :views => @post.view_count,
                    :popularity => @post.popularity_index })
  end

  def summary
    { :id     => @post.id,
      :title  => @post.title,
      :author => @post.author_name }
  end
end
class PostController < ApplicationController
  before_filter :require_user

  def show
    @post = current_organization.posts.find(params[:id])

    respond_to do |format|
      format.html
      format.json { s = PostSerializer.new(@post, current_user)
                    render :json => s.to_json }
    end
  end
end

Version #5

class WidgetPresenter
  def initialize(widget)
    @widget = widget
  end

  def details(user)
    if @widget.owned_by?(user)
      @widget.details
    else
      ""
    end
  end
end

Version #6

https://gist.github.com/4341122

class CommentDecorator
  def initialize(comment)
    @comment = comment
  end

  def to_json
    {:author => comment.author.name, 
     :body   => comment.body,
     :date   => comment.created_at }.to_json 
  end

  def to_html
    # use your imagination here
  end
end

Clone this wiki locally