Sử dụng service object giúp DRY code trong controller trong Rails
I. Giới thiệu Trong các project của Rails, nhiều khi ta phải xử lý rất nhiều logic trong các hàm trong controller, việc này gây khó khăn trong việc hiểu code đồng thời khiến code của ta trông phức tạp hơn, dễ xảy ra sai sót, sử dụng service objects sẽ giúp chúng ta làm sạch controller đồng thời ...
I. Giới thiệu
Trong các project của Rails, nhiều khi ta phải xử lý rất nhiều logic trong các hàm trong controller, việc này gây khó khăn trong việc hiểu code đồng thời khiến code của ta trông phức tạp hơn, dễ xảy ra sai sót, sử dụng service objects sẽ giúp chúng ta làm sạch controller đồng thời tránh DRY code, giảm thiểu các tính toán phức tạp dài dòng trong controller.
II. Cài đặt và sử dụng
Tạo thư mục services trong app/
ví dụ: tạo service giúp việc kiểm tra xem liệu record có tồn tại hay không, ta tạo file sau: app/services/check_work_performance_existed.rb
Class được định nghĩa trong file trên bao gồm các phần:
- phương thức khởi tạo với thông số là các input nhập vào
- các hàm xử lý logic
- giá trị trả về.
ví dụ:
class CheckWorkPerformanceExisted
def initialize sprint, params
sprint = sprint
params = params
end
def check_WPD_if_existed
check_WPD_existed
end
private
def check_WPD_existed
if params[:master_sprint_id] && params[:activity_id]
master_sprint_id = params[:master_sprint_id]
activity_id = params[:activity_id]
user_id = params[:user_id]
work_performances = sprint.work_performances.of_activity_in_day(user_id,
master_sprint_id, activity_id)
end
work_performances
end
end
trong đó, hàm khởi tạo `initialize(sprint, params)` khởi tạo giá trị cho đối tượng trong class `CheckWorkPerformanceExisted`, các giá trị này cần thiết cho việc sử dụng cho việc tính toán hay sử lý logic trong các hàm bên dưới như `check_WPD_existed`.
Vậy sau khi tạo 1 đối tượng service thì làm thế nào để sử dụng nó trong controller?
Trong controller, trong hàm cần xử lý các logic trong class trên, ta tạo 1 đối tượng mới bằng cách dùng câu lệnh new và gọi đến hàm cần dùng trong class trên.
ví dụ:
work_performances = CheckWorkPerformanceExisted.new(sprint, params).check_WPD_if_existed
hàm `new` sẽ khởi tạo đối tượng mới theo các `input` trong định nghĩa hàm `initialize` đã định nghĩa trong class, như vậy `work_performances` là một đối tượng của class `CheckWorkPerformanceExisted` và lưu giá trị trả về trong hàm `check_WPD_if_existed `, và ta có thể tiếp tục xử lý các logic khác trong controller
def update
if params[:master_sprint_id] && params[:task_id] && params[:user_id]
work_performances = CheckWorkPerformanceExisted.new(sprint, params)
.check_WPD_if_existed
respond_to do |format|
if work_performances.any?
format.json {render json: {existed: :true, wpds: work_performances}}
else
format.json {render json: {existed: :false, wpds: []}}
end
end
end
end
Như vậy, chỉ với 1 câu lệnh trong controller, ta có thể rút gọn các dòng code phức tạp dài dòng, giúp controller trông gọn hơn, dễ hiểu hơn.
Mọi người có thể đọc nhiều hơn tại đây:
https://www.netguru.co/blog/service-objects-in-rails-will-help