Ruby on Rails cung cấp mọi thứ bạn cần để tạo một ứng dụng của mình một cách nhanh chóng, nhưng khi ứng dụng của bạn bắt đầu phát triển, bạn sẽ gặp phải các tình huống models và controllers phình to ra, trong còng cành và khó kiểm soan khi phải xử lý các nghiệp vụ và logic phức tạp, bao gồm các chức năng đòi hỏi chúng ta phải tương tác với rất nhiều các Model khác nhau, không nhắm đến 1 model cụ thể.
Service Object chính là một trong những giải pháp cho vấn đề này. Nó được sinh ra như một nơi chứa các business logic khác nhau mà trong đó đối tượng xử lí không hoàn toàn thuộc về model nào.
Lợi ích của Service Object là nó giúp chúng ta tập trung toàn bộ logic các chức năng vào trong 1 object riêng biệt mà không cần phải chia nhỏ nó vào các controller và model như cách thông thường. Lúc nào cần dùng đến thì chúng ta mới gọi object đó ra. Chính vì khối logic được tập trung hết vào trong 1 object nên sẽ tối giản controller và model đi rất nhiều, code clean và quá trình maintain sau này cũng đỡ vất vả hơn.
service object class
classes là một lựa chọn tốt nếu bạn muốn lưu dữ liệu vào instance variables.
class ServiceObject
def call(arg1, arg2, ...etc)
new(arg1, arg2, ...etc).call
end
private
def initialize(arg1, arg2, ...etc)
@var = arg1
@var = arg2
...etc
end
def call
# Logic goes here
end
end
service object module
Nếu bạn không muốn lưu dữ liệu vào instance variables, thì một module là một lựa chọn nhẹ nhàng hơn
module ServiceObject
def perform(arg1, arg2, ...etc)
# Logic goes here
end
end
cách sự dụng service object
Thông thường thì trong Rails các services của hệ thống sẽ được tập trung ở trong thư mục app/services. Tùy vào tính đặc thù và độ phức tạp của dự án mà chúng ta có thể chia nhỏ services ra thành nhiều mục con. Ở ví dụ này mình sẽ tạo một service object có tên là CalculatorService:
class CalculatorService
def initialize(number_1, number_2, method = nil)
@number_1 = number_1
@number_2 = number_2
@method = method
end
def perform
case method
when :addition
addition
when :subtraction
subtraction
when :multiplication
multiplication
when :division
division
else
"You have not selected a calculation method"
end
end
private
attr_accessor :number_1, :number_2, :method
def addition
number_1 + number_2
end
def subtraction
number_1 - number_2
end
def multiplication
number_1 * number_2
end
def division
return "Denominator cann't be zero" if number_2.zero?
(number_1 / number_2).to_f
end
end
class CalculatorService khởi tạo với các tham số number_1, number_2, method
và có các phương thưc addition
, subtraction
, multiplication
, division
chúng ta có thể gọi đến service object bất kể đâu và bất kể khi nào chúng ta cấn dùng đến nó
result = CalculatorService.new(5, 7, :addition).perform
=> 12
lưu ý: nếu service object của bạn là một module thì bạn phải include hay extend tùy vào mục đích sử dụng của bạn như thế nào
tổng kết
Bài viết nhằm chia sẻ một chút kiến thức của mình và cách sử dụng cơ bản về Service Object, bài viết còn nhiều hạn chế, cảm ơn các bạn đã đọc.
Tài liệu tham khảo:
https://www.thegreatcodeadventure.com/service-objects-in-rails/ https://www.toptal.com/ruby-on-rails/rails-service-objects-tutorial https://blog.appsignal.com/2020/06/17/using-service-objects-in-ruby-on-rails.html