lib/quby/answers/services/updates_answers.rb
# frozen_string_literal: true
require 'quby/answers/services/filters_answer_value'
require 'quby/answers/services/outcome_calculation'
module Quby
module Answers
module Services
class UpdatesAnswers
attr_reader :answer
def initialize(answer)
@answer = answer
end
def update(new_attributes = {})
save_raw_params_on_error(new_attributes) do
attribute_filter = FiltersAnswerValue.new(answer.questionnaire)
attribute_filter.filter(new_attributes).each { |name, value| answer.send("#{name}=", value) }
answer.extend AnswerValidations
answer.cleanup_input
answer.validate_answers
if answer.errors.empty?
if new_attributes["rendered_at"].present?
started_at = Time.at(new_attributes["rendered_at"].to_i)
else
started_at = nil
end
answer.mark_completed(started_at)
answer.outcome = OutcomeCalculation.new(answer).calculate
Quby.answers.update!(answer)
succeed!
else
if defined? ::Roqua::Support
::Roqua::Support::Errors.report(Quby::ValidationError.new(answer.errors.full_messages))
end
fail!
end
end
end
def on_success(&block)
@success_callback = block
end
def on_failure(&block)
@failure_callback = block
end
protected
def save_raw_params_on_error(new_attributes)
if new_attributes.respond_to?(:to_unsafe_h)
answer.raw_params = new_attributes.to_unsafe_h
else
answer.raw_params = new_attributes
end
backup_answer = answer.clone
yield
rescue
# we dont save answer since it probably has a weird state now, instead we save the a clone of answer
# that just has the raw_params set on it, so we can do data recovery with the raw_params
backup_answer.raw_params['could_not_update_at'] = DateTime.now.to_i # to note this is was a failed update
Quby.answers.update!(backup_answer)
raise
end
def succeed!
@success_callback.call if @success_callback
end
def fail!
@failure_callback.call if @failure_callback
end
end
end
end
end