iT邦幫忙

2021 iThome 鐵人賽

DAY 20
0
自我挑戰組

冒險村-30 Day Ruby on Rails Tips Challenge系列 第 20

冒險村20 - Design Pattern(1) - Decorator

  • 分享至 

  • xImage
  •  

20 - Design Pattern(1) - Decorator

Decorator pattern 的原理是,增加一個修飾類包裹原來的 class,包裹的方式是在修飾類的構造函數中將原來的類以參數的形式傳入。裝飾類實現新的功能,但是,在不需要用到新功能的地方,它可以直接調用原來的類中的方法。修飾類必須和原來的類有相同的接口。

直接來看如何使用:

Create app/decorators folder

並在 folder 下可以先建立以下兩個檔案,稍後會來修改內容

  • base_decorator.rb
  • user_decorator.rb

Add decorate to ApplicationHelper

新增一個共用的方法取名為 decorate,可以方便之後在 controller 直接 helpers.decorate
來將重複的 code 整理起來,當然也會有不符合規則的時候,所以允許帶入 args。

  # frozen_string_literal: true
  module ApplicationHelper
    def decorate(model, decorate_class = nil)
      (decorate_class || "#{model.class}Decorator".constantize).new(model)
    end
  end

Add app > decorators > base_decorator.rb

這邊將為 decorator 的父層。主要重點是繼承在 SimpleDelegator 下,這個看文件其實滿好理解的。

  # frozen_string_literal: true
  class BaseDecorator < SimpleDelegator
    def decorate(model, decorate_class = nil)
      ApplicationController.helpers.decorate(model, decorate_class)
    end
  end

Add app > decorators > user_decorator.rb

可以將 view 的邏輯丟到 decorator 內,簡單以 User 常有的 first_name, last_name 來說,在 DB 內存成兩個欄位,不過畫面上通常都會是想要直接顯示兩個欄位加起來作為使用者的名稱,這時候只要在 view 直接 @xxx.full_name 即可。

  # frozen_string_literal: true
  class UserDecorator < BaseDecorator
    def full_name
      "#{first_name} #{last_name}"
    end
  end

Init instance variable

  # frozen_string_literal: true
  class UsersController < ApplicationController
    def show
      @user_decorator = helpers.decorate(current_user)
    end

    private

    def current_user
      User.find(params[:id])
    end
  end

View

  # show.html.erb
  <%= @user_decorator.full_name %>
  <%= @user_decorator.email %>

參考資料

My blog


上一篇
冒險村19 - Activerecord-import
下一篇
冒險村21 - draper
系列文
冒險村-30 Day Ruby on Rails Tips Challenge30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言