diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index cf7ef6c..0000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Lint -on: [push, pull_request] -jobs: - rubocop: - runs-on: ubuntu-latest - strategy: - fail-fast: true - - steps: - - uses: actions/checkout@v2 - - uses: ruby/setup-ruby@v1 - with: - ruby-version: 2.6 - - run: gem install bundler - - run: bundle install --jobs=$(nproc) --retry=$(nproc) - - run: bin/rubocop -P - - reek: - runs-on: ubuntu-latest - strategy: - fail-fast: true - - steps: - - uses: actions/checkout@v2 - - uses: ruby/setup-ruby@v1 - with: - ruby-version: 2.6 - - run: gem install bundler - - run: bundle install --jobs=$(nproc) --retry=$(nproc) - - run: bin/reek . diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index b54afb7..943492d 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -2,23 +2,17 @@ name: RSpec on: [push, pull_request] jobs: tests: - env: - COV: true - runs-on: ubuntu-latest strategy: - fail-fast: true + fail-fast: false matrix: - # ruby: [2.5, 2.6, 2.7, jruby, truffleruby] - ruby: [2.5, 2.6, 2.7] + ruby: ['3.3', '3.4'] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} - - run: gem install bundler - - run: bundle install --jobs=$(nproc) --retry=$(nproc) - - run: bin/rspec - + bundler-cache: true + - run: bundle exec rspec diff --git a/active_campaign.gemspec b/active_campaign.gemspec index 700cda6..006aaf4 100644 --- a/active_campaign.gemspec +++ b/active_campaign.gemspec @@ -29,7 +29,6 @@ Gem::Specification.new do |spec| spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ['lib'] - spec.add_dependency 'activesupport', '>= 4.0', '< 8.0' - spec.add_dependency 'faraday', '>= 1.0', '< 3.0' + spec.add_dependency 'faraday', '>= 1.2', '< 3.0' spec.add_dependency 'oj', '>= 3.0', '< 4.0' end diff --git a/lib/active_campaign.rb b/lib/active_campaign.rb index 673e33f..b5d8ddb 100644 --- a/lib/active_campaign.rb +++ b/lib/active_campaign.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'faraday' +require 'oj' require 'active_campaign/version' require 'active_campaign/errors' diff --git a/lib/active_campaign/api.rb b/lib/active_campaign/api.rb index 724c484..9a2de2d 100644 --- a/lib/active_campaign/api.rb +++ b/lib/active_campaign/api.rb @@ -40,7 +40,7 @@ def endpoints(*endpoints) def endpoint(endpoint) require "active_campaign/api/#{endpoint}" - class_eval { include API.const_get(endpoint.to_s.camelize) } + class_eval { include API.const_get(TransformHash.camelize(endpoint.to_s)) } rescue LoadError, NameError raise DependencyMissing, endpoint end diff --git a/lib/active_campaign/faraday/middleware/request.rb b/lib/active_campaign/faraday/middleware/request.rb index dec1dee..997b7a4 100644 --- a/lib/active_campaign/faraday/middleware/request.rb +++ b/lib/active_campaign/faraday/middleware/request.rb @@ -9,8 +9,6 @@ module Middleware # @author Mikael Henriksson # class Request < ::Faraday::Middleware - dependency 'oj' - include TransformHash def initialize(app, headers) diff --git a/lib/active_campaign/faraday/middleware/response.rb b/lib/active_campaign/faraday/middleware/response.rb index bcd38f6..6b40559 100644 --- a/lib/active_campaign/faraday/middleware/response.rb +++ b/lib/active_campaign/faraday/middleware/response.rb @@ -12,9 +12,7 @@ module Middleware # # @author Mikael Henriksson # - class Response < ::Faraday::Response::Middleware - dependency 'oj' - + class Response < ::Faraday::Middleware include TransformHash # Override this to modify the environment after the response has finished. diff --git a/lib/active_campaign/transform_hash.rb b/lib/active_campaign/transform_hash.rb index a7fae40..756d92a 100644 --- a/lib/active_campaign/transform_hash.rb +++ b/lib/active_campaign/transform_hash.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require 'active_support/core_ext/string' - module ActiveCampaign # # Utility module for manipulating hashes, arrays and values @@ -35,7 +33,7 @@ def transform_keys(hash, *new_case) # @return [Symbol] the transformed key # def transform_key(key, *new_case) - key.to_s.public_send(*new_case).to_sym + inflect(key.to_s, *new_case).to_sym end # @@ -68,5 +66,38 @@ def transform_array(collection, *new_case) end end end + + # + # Changes the case of a string + # + # @param [String] string the string to change + # @param [Symbol] style `:underscore` or `:camelcase` + # @param [Symbol] first_letter `:upper` or `:lower`, only used by `:camelcase` + # + # @return [String] + # + def inflect(string, style, first_letter = :upper) + case style + when :underscore then underscore(string) + when :camelcase then camelize(string, first_letter) + else raise ArgumentError, "unknown case #{style.inspect}" + end + end + + # The rules below are the ActiveSupport ones without acronyms or namespace (::) handling. They live here + # so an application's inflection config can't change the keys sent to the API. + def underscore(string) + return string unless /[A-Z-]/.match?(string) + + string + .gsub(/([A-Z])(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) { "#{Regexp.last_match(1) || Regexp.last_match(2)}_" } + .tr('-', '_') + .downcase + end + + def camelize(string, first_letter = :upper) + head = first_letter == :lower ? string.sub(/\A\w/, &:downcase) : string.sub(/\A[a-z\d]*/, &:capitalize) + head.gsub(/_([a-z\d]*)/i) { Regexp.last_match(1).capitalize } + end end end diff --git a/spec/lib/active_campaign/api/deal_stages_spec.rb b/spec/lib/active_campaign/api/deal_stages_spec.rb index 7c2806c..64fc10f 100644 --- a/spec/lib/active_campaign/api/deal_stages_spec.rb +++ b/spec/lib/active_campaign/api/deal_stages_spec.rb @@ -8,10 +8,6 @@ include_context 'with deal_stage params' - after do - client.delete_deal_stage(response.dig(:deal, :id)) - end - # rubocop:disable RSpec/ExampleLength it 'returns a deal_stage hash' do expect(response).to include_json( diff --git a/spec/lib/active_campaign/api/fields_spec.rb b/spec/lib/active_campaign/api/fields_spec.rb index 7393803..5819901 100644 --- a/spec/lib/active_campaign/api/fields_spec.rb +++ b/spec/lib/active_campaign/api/fields_spec.rb @@ -74,8 +74,7 @@ end it 'makes the custom field irretrievable' do - show_response = client.show_field(field_id) - expect(show_response).not_to include_json(field: expected_field_response) + expect { client.show_field(field_id) }.to raise_error(ActiveCampaign::ResourceNotFound) end end diff --git a/spec/lib/active_campaign/api/pipelines_spec.rb b/spec/lib/active_campaign/api/pipelines_spec.rb index 91b337c..1122eae 100644 --- a/spec/lib/active_campaign/api/pipelines_spec.rb +++ b/spec/lib/active_campaign/api/pipelines_spec.rb @@ -18,10 +18,6 @@ include_context 'with pipeline params' - after do - client.delete_pipeline(response.dig(:pipeline, :id)) - end - it 'returns a pipeline hash' do expect(response).to include_json( deal_group: { diff --git a/spec/lib/active_campaign/api/tags_spec.rb b/spec/lib/active_campaign/api/tags_spec.rb index 6e1182f..7f60262 100644 --- a/spec/lib/active_campaign/api/tags_spec.rb +++ b/spec/lib/active_campaign/api/tags_spec.rb @@ -64,8 +64,7 @@ end it 'makes the tag irretrievable' do - show_response = client.show_tag(tag_id) - expect(show_response).not_to include_json(tag: expected_tag_response) + expect { client.show_tag(tag_id) }.to raise_error(ActiveCampaign::ResourceNotFound) end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 5842cfe..741cbfc 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -8,6 +8,7 @@ require 'active_campaign' +require_relative 'support/cleanup' require_relative 'support/shared_contexts' require_relative 'support/webmock' require_relative 'support/vcr' diff --git a/spec/support/cleanup.rb b/spec/support/cleanup.rb new file mode 100644 index 0000000..faa8c33 --- /dev/null +++ b/spec/support/cleanup.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# The client raises ResourceNotFound on 404, and cleanup hooks often delete a +# resource the example itself already deleted. +module Cleanup + def cleanup + yield + rescue ActiveCampaign::ResourceNotFound + nil + end +end + +RSpec.configure do |config| + config.include Cleanup +end diff --git a/spec/support/shared_contexts.rb b/spec/support/shared_contexts.rb index 0771376..5f4788c 100644 --- a/spec/support/shared_contexts.rb +++ b/spec/support/shared_contexts.rb @@ -31,7 +31,7 @@ end after do - client.delete_account(account_id) if account_id + cleanup { client.delete_account(account_id) } if account_id end end @@ -80,6 +80,6 @@ end after do - client.delete_account_contact(account_contact_id) if account_contact_id + cleanup { client.delete_account_contact(account_contact_id) } if account_contact_id end end diff --git a/spec/support/shared_contexts/with_contact_tag.rb b/spec/support/shared_contexts/with_contact_tag.rb index 650f771..c17bfa6 100644 --- a/spec/support/shared_contexts/with_contact_tag.rb +++ b/spec/support/shared_contexts/with_contact_tag.rb @@ -28,6 +28,6 @@ let(:contact_tag_id) { contact_tag[:id] } after do - client.delete_contact_tag(contact_tag_id) if contact_tag_id + cleanup { client.delete_contact_tag(contact_tag_id) } if contact_tag_id end end diff --git a/spec/support/shared_contexts/with_field.rb b/spec/support/shared_contexts/with_field.rb index 50700d2..8f1e8d8 100644 --- a/spec/support/shared_contexts/with_field.rb +++ b/spec/support/shared_contexts/with_field.rb @@ -39,7 +39,7 @@ let(:field_id) { field[:id] } after do - client.delete_field(field_id) if field_id + cleanup { client.delete_field(field_id) } if field_id end end @@ -162,6 +162,6 @@ let(:rel_id) { field_rel[:id] } after do - client.delete_field_rel(rel_id) if rel_id + cleanup { client.delete_field_rel(rel_id) } if rel_id end end diff --git a/spec/support/shared_contexts/with_field_value.rb b/spec/support/shared_contexts/with_field_value.rb index 647f1b4..7aa23fe 100644 --- a/spec/support/shared_contexts/with_field_value.rb +++ b/spec/support/shared_contexts/with_field_value.rb @@ -29,6 +29,6 @@ let(:field_value_id) { field_value[:id] } after do - client.delete_field_value(field_value_id) if field_value_id + cleanup { client.delete_field_value(field_value_id) } if field_value_id end end diff --git a/spec/support/shared_contexts/with_tag.rb b/spec/support/shared_contexts/with_tag.rb index 3a763c1..e170b49 100644 --- a/spec/support/shared_contexts/with_tag.rb +++ b/spec/support/shared_contexts/with_tag.rb @@ -27,6 +27,6 @@ let(:tag_id) { tag[:id] } after do - client.delete_tag(tag_id) if tag_id + cleanup { client.delete_tag(tag_id) } if tag_id end end