Ga Tech

1.01 everyday

Service Objects 整理架構

目前專案是按照 這篇 的方式來組織 Rails 專案架構:
該篇主要也是使用 service objects 的方式來組織,把較複雜的處理從 Controllers 當中抽出來並放到 services 資料夾中。
比較不同的是該作者不推薦以 XXXService 的方式來命名 service objects (比如 TransactionService);反而推薦一個行為就拆成一個 service,並且以「動詞」為開頭來命名,例如 ApproveTransation, CancelTransaction, BlockAccount…等,如果是同樣類型的 service 還可以另外用個資料夾包起來 (例如 app/services/transaction/approve.rb, app/services/transaction/cancel.rb…)

好處是可以很容易從名稱就知道這個 service object 的目的是什麼,而且簡化每個 object 的責任以方便測試。

1
2
3
4
5
6
7
8
9
# app/services/accept_invite.rb
class AcceptInvite
def self.call(invite, user)
invite.accept!(user)
UserMailer.invite_accepted(invite).deliver
end
end

今天又看到 另一篇 有趣的整理方式:
作者主要想法是不要把 service objects 都放在同一個地方,畢竟有些是只跟 controller 有關,有些只跟 model 有關,建議把這些 POROs 放到跟其有關的目錄底下。

例如跟 controller 有關的:

1
2
3
4
controllers
├── dashboard_controller
│ └── user_list.rb
└── dashboard_controller.rb
1
2
3
4
5
# app/controllers/dashboard_controller/user_list.rb
class DashboardController::UserList
# codes codes codes
end
1
2
3
4
5
6
7
8
9
class DashboardController < ApplicationController
def index
@users = UserList.new(current_user,
page: params[:page],
per_page: params[:per_page],
sort_by: params[:sort_by],
order_asc: params[:order_asc]).all
end
end

或是跟 model 有關的:

1
2
3
4
5
6
models
├── user
│ └── following_policy.rb
│ └── lockable.rb
│ └── settings.rb
└── user.rb
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
28
29
30
31
32
33
# app/models/user/lockable.rb
module User::Lockable
def lock_access!
update(locked_at: Time.now)
UserMailer.account_locked_email(self).deliver
end
# ...
end
# app/models/user/settings.rb
module User::Settings
extend ActiveSupport::Concern
included do
store_accessor :settings
end
# ...
end
# app/models/user/following_policy.rb
class User::FollowingPolicy
attr_reader :current_user, :other_user, :account_verification
def initialize(current_user, other_user)
@current_user = current_user
@other_user = other_user
@account_verification = current_user.account_verification
end
# ...
end

很喜歡 Rails pure MVC 架構的人可以試試 :)

Comments