07/09/2018, 16:51

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

0