冒險村22 - Design Pattern(2) - Presenter

22 - Design Pattern(2) - Presenter

Presenter pattern 的原理是,是 Model-View-Controller(MVC) 架構模式衍生出來的一個部分,主要用於建立使用者的介面接口。 在 MVP 中,Presenter 承擔了 中間人 的功能。在 MVP 中,所有邏輯的部份都會寫在 Presenter 內。事實上,其實與 Decorator 有點相似,通常有些些微的差異,但通常只會選擇兩個其中一個來整理,也沒有一定的通則,主要還是以團隊內的方式為主。

直接來看如何使用:

假設我有一張 Log 的表,裡面 operator 欄位紀錄了 User 誰操作了某項東西,所以紀錄這個 Log,並且知道 Source -> Target 從 A 到 B,這時候想要後台的前端可以看到 Log 紀錄,隨便舉個例子。

Create app/presenters folder

  • user_log_presenter.rb

Add Presenter to Controller

假設 Log 是在 TrackController 內的 show 來顯示,範例如下:

1
2
3
4
5
6
7
8
# frozen_string_literal: true
class TrackingController < ApplicationController
def show
@user_logs = UserLogPresenter.new(user_id)
end

# ...
end

Add app > presenters > user_log_presenter.rb

Enumerable include 近來提供 each 等等方法,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# frozen_string_literal: true
class UserLogPresenter
include Enumerable

def initialize(user_id)
@user_id = user_id
end

def each(&_block)
logs.each do |log|
yield format(log)
end
end

def format(log)
{
user: User.find(log.operator),
source: log.source,
target: log.target,
created_at: log.created_at
}
end

def logs
@logs ||= Log.where(operator: user_id)
end
end

View

1
2
3
4
5
6
@user_logs.each do |log|
<th><%= log[:user] %></th>
<th><%= log[:source] %></th>
<th><%= log[:target] %></th>
<th><%= log[:created_at] %></th>
end

註: 想理解兩者的差異也可以參考這篇的比較 Ruby on Rails patterns - decorator vs presenter,雖然目前我也沒有可以完全的分懂 orz

參考資料