Service object trong rails

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


All Rights Reserved