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
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 :)