关于rails中的演示者模式.这是一个更好的方法吗?

Tot*_*.js 5 mvp ruby-on-rails

我有我的模特:

def presenter
   @presenter ||= ProfilePresenter.new(self)
   @presenter
end
Run Code Online (Sandbox Code Playgroud)

ProfilePresenter是一个具有get_link(),get_img_url(size),get_sex(),get_relationship_status()等方法的类,以及与模型无关的其他方法,甚至与控制器无关,但在视图.

所以现在我通过这样做来使用它们:

Profile.presenter.get_link
# or
Profile.presenter.get_img_url('thumb') # returns the path of the image. is not used to make a db query
Run Code Online (Sandbox Code Playgroud)

我以为我认为我错过了主持人的真实概念..但这就是我试图存档的内容,怎么可以称之为?

tad*_*man 16

通常这种事情是通过辅助方法处理的,例如:

def profile_link(profile)
  profile.link ? content_tag(:a, h(profile.name), :href => profile.link) : 'No profile'
end
Run Code Online (Sandbox Code Playgroud)

遗憾的是,您无法在视图时扩展模型的Presenter样式辅助方法中进行分层.它们需要以一种参数,一种反OO的程序方式被调用.

Rails MVC区域不完全支持Presenter方法,因为它需要绑定到视图才能访问正确呈现内容所需的各种帮助程序方法,以及可能影响表示的会话信息.

更强大的方法可能是做这样的事情:

class ProfilePresenter
  def initialize(view, profile)
    @profile = profile
    @view = view

    yield(self) if (block_given?)
  end

  def link
    @profile.link ? @view.content_tag(:a, @view.h(profile.name), :href => @profile.link) : 'No profile'
  end

  def method_missing(*args)
    @profile.send(*args)
  end
end
Run Code Online (Sandbox Code Playgroud)

这将在您的视图中显示为:

<% ProfilePresenter.new(self, @profile) do |profile| %>
<div><%= profile.link %>
<% end %>
Run Code Online (Sandbox Code Playgroud)

你可以通过制作一个有点疯狂的帮助方法来简化这个调用:

def presenter_for(model)
  "#{model.class}Presenter".constantize.new(self, model) do |presenter|
    yield(presenter) if (block_given?)
  end
end
Run Code Online (Sandbox Code Playgroud)

这意味着你有一个更简单的电话:

<% presenter_for(@profile) do |profile| %>
<div><%= profile.link %>
<% end %>
Run Code Online (Sandbox Code Playgroud)