ruby-on-railsrubyservice-object

How to minimize 3 ServiceObjects to 1 per 1 action


I have the Worker with an action with some code and 3 calls of Service Objects in it. 2 Service Objects for saving data to base during different states of object saving (update started, update completed). And 1 for counting the percentage of progress.

I know, it should be 1 Service Object per 1 action. How should I avoid the using of over head Service Objects? Or how should I refactor my code, for example, devide it into parts?

Sorry, if I have mistakes in question style. I was trying to explain situation clearly.

csv_worker.rb

def perform(import_id)

  ...

  @import = Import.find(import_id)

  ImportStartedUpdateJobService.call(@import)  

  users = []  
  row_hash = {}
  result = ''

  CSV.foreach(@import.file.path, headers: true).with_index do |row, index|
    row_hash = row.to_h
    row_hash['import_id'] = @import.id

    # The day is put on the first place
    # to make the data valid for saving in DB
    row_hash = make_the_date_valid(row_hash)    

    user = User.new(row_hash)

    if user.valid?
      ...
    end

    @import.percentage = ImportPercentageUpdateJobService.call(@import)
    @import.save if (index % 10).zero? 

    if (index % 1000).zero? 
      User.import(users)
      users = []
    end  
  end  

  User.import(users)
  ImportCompletedUpdateJobService.call(@import)

  puts 
end    

import_started_update_job_service.rb

def initialize(import)
  @import = import
end

def call
  @import.count_of_lines_in_csv = CSV.read(@import.file.path).count - 1
  @import.started_at            = Time.now
  @import.import_status         = 'started'
  @import.save
end

import_completed_update_job_service.rb

...
def call
  @import.completed_at  = Time.now
  @import.import_status = 'completed'
  @import.percentage = 100
  @import.save
end

import_percentage_update_job_service.rb

...
def call
  @import.percentage = if @import.count_of_lines_in_csv.positive?
                         (@import.count_of_created_users +
                          @import.count_of_not_created_users).to_f /
                           @import.count_of_lines_in_csv *
                           100
                       end

  @import.percentage.to_i  
end

Solution

  • It was okay to make a lot of ServiceObjects. Every of them should solve 1 issue. Even if we have many SObjects per 1 controller or per 1 action.

    I got it :)