From a15596a12615ab44bd1e9a97ca99f5ec136190ac Mon Sep 17 00:00:00 2001 From: Urban Rotnik Date: Thu, 30 May 2019 20:24:11 +0200 Subject: [PATCH] Add ImportProtocolService --- .../import_protocol_from_client_service.rb | 62 +++++++++++++++++++ config/initializers/constants.rb | 6 ++ ...mport_protocol_from_client_service_spec.rb | 37 +++++++++++ 3 files changed, 105 insertions(+) create mode 100644 app/services/protocols/import_protocol_from_client_service.rb create mode 100644 spec/services/protocols/import_protocol_from_client_service_spec.rb diff --git a/app/services/protocols/import_protocol_from_client_service.rb b/app/services/protocols/import_protocol_from_client_service.rb new file mode 100644 index 000000000..565aa62a0 --- /dev/null +++ b/app/services/protocols/import_protocol_from_client_service.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +module Protocols + class ImportProtocolFromClientService + extend Service + + attr_reader :errors, :pio_protocol + + def initialize(protocol_client_id:, protocol_source:, user_id:, team_id:) + @id = protocol_client_id + @protocol_source = protocol_source + @user = User.find user_id + @team = Team.find team_id + @errors = {} + end + + def call + return self unless valid? + + # Catch api errors here, json invalid, also wrong/not found normalizer? + normalized_hash = client.load_protocol(id: @id) + # Catch api errors here + + pio = ProtocolImporters::ProtocolIntermediateObject.new(normalized_json: normalized_hash, + user: @user, + team: @team) + @pio_protocol = pio.build + + if @pio_protocol.valid? + # catch errors during import here + pio.import + # catch errors during import here + else + # Add AR errors here + # @errors[:protcol] = pio.protocol.errors.to_json...? somehow + @errors[:protocol] = pio.protocol.errors + end + + self + end + + def succeed? + @errors.none? + end + + private + + def valid? + unless @id && @protocol_source && @user && @team + @errors[:invalid_arguments] = { '@id': @id, '@protocol_source': @protocol_source, 'user': @user, 'team': @team } + .map { |key, value| "Can't find #{key.capitalize}" if value.nil? }.compact + return false + end + true + end + + def client + endpoint_name = Constants::PROTOCOLS_ENDPOINTS.dig(*@protocol_source.split('/').map(&:to_sym)) + "ProtocolImporters::#{endpoint_name}::ProtocolNormalizer".constantize.new + end + end +end diff --git a/config/initializers/constants.rb b/config/initializers/constants.rb index 2b3c5caea..2f5507712 100644 --- a/config/initializers/constants.rb +++ b/config/initializers/constants.rb @@ -193,6 +193,12 @@ class Constants # Protocol importers #============================================================================= + PROTOCOLS_ENDPOINTS = { + protocolsio: { + v3: 'ProtocolsIO::V3' + } + }.freeze + PROTOCOLS_IO_V3_API = { base_uri: 'https://www.protocols.io/api/v3/', default_timeout: 10, diff --git a/spec/services/protocols/import_protocol_from_client_service_spec.rb b/spec/services/protocols/import_protocol_from_client_service_spec.rb new file mode 100644 index 000000000..ccfdcf921 --- /dev/null +++ b/spec/services/protocols/import_protocol_from_client_service_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe Protocols::ImportProtocolFromClientService do + let(:user) { create :user } + let(:team) { create :team } + let(:service_call) do + Protocols::ImportProtocolFromClientService + .call(protocol_client_id: 'id', protocol_source: 'protocolsio/v3', user_id: user.id, team_id: team.id) + end + let(:normalized_response) do + JSON.parse(file_fixture('protocols_importer/protocols_io/v3/normalized_single_protocol.json').read) + .to_h.with_indifferent_access + end + + context 'when have invalid arguments' do + it 'returns an error when can\'t find user' do + allow(User).to receive(:find).and_return(nil) + + expect(service_call.errors).to have_key(:invalid_arguments) + end + end + + context 'when have valid arguments' do + before do + allow_any_instance_of(ProtocolImporters::ProtocolsIO::V3::ProtocolNormalizer) + .to(receive(:load_protocol).and_return(normalized_response)) + # Do not generate and request real images + allow(ProtocolImporters::AttachmentsBuilder).to(receive(:generate).and_return([])) + end + it 'Adds Protocol record' do + expect { service_call }.to(change { Protocol.all.count }.by(1)) + end + # more tests will be implemented when add error handling to service + end +end