presenter on rails

https://github.com/angelfan/DayDayUp/blob/master/note/presenter.md

presenter on rails

ruby on rails 属于 MVC 框架, 对于简单的应用三层可能就够用了, 但是当应用越来越复杂可能就需要更多的抽象层来满足业务需求, 比如service, presenter 比如有些人认为应用逻辑(业务逻辑)不应该放在数据层(Model),或者一个 Model 只应该管好他自己的事情,多个 Model 的融合需要另外的类来做代理。

Model != View

很多情况下, view中会有这样的类似写法 @article.published? && @article.user_type == 'Admin' 也许可以把他放到model中定义出一个方法, 比如

class Artice < ActiveRecord::Base
    def published_by_admin?
        published? && user_type == 'Admin
    end
end

或者你也可以把他放到 helper中去 然后view中就可以这样用@article.published_by_admin 但是随着逻辑越来越多, model中类似的方法也会越来越多, 但是model中应该主要用来放业务逻辑 所以需要额外抽象出presenter层来处理

Demo

## 代码链接 https://github.com/railscasts/287-presenters-from-scratch
class BasePresenter
  def initialize(object, template)
    @object = object
    @template = template
  end

  def object
    @object
  end

private

  def self.presents(name)
    define_method(name) do
      @object
    end
  end

  def h
    @template
  end

  # this allows any template methods to be called directly from presenter code.
  def method_missing(*args, &block)
    # TODO check for @template.respond_to? and return raw values if nil
    @template.send(*args, &block)
  end
end

class UserPresenter < BasePresenter
  presents :user
  delegate :username, to: :user

  def full_name
    "#{first_name}-#{last_name}"
  end
end


# helper 中增加该方法
module ApplicationHelper
  def present(object, klass = nil)
    klass ||= "#{object.class}Presenter".constantize
    presenter = klass.new(object, self)
    yield presenter if block_given?
    presenter
  end
end

# in view
<% present @user do |user_presenter| %>
    <p><%= user_presenter.fullname %></p>
<% end %>

这样不管是model 还是 helper都会变得很干净, 最重要的是 变得更容易测试

推荐的gem Draper

posted @ 2016-03-07 22:32  耿小曾  阅读(293)  评论(0编辑  收藏  举报