eclaircir 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +27 -0
  3. data/.travis.yml +11 -0
  4. data/Gemfile +17 -0
  5. data/LICENSE +21 -0
  6. data/README.md +70 -0
  7. data/Rakefile +12 -0
  8. data/TODO.md +75 -0
  9. data/bin/console +10 -0
  10. data/bin/test.rb +17 -0
  11. data/eclaircir.gemspec +20 -0
  12. data/lib/eclaircir/api_models/attributes/nullable_date_time.rb +15 -0
  13. data/lib/eclaircir/api_models/attributes.rb +8 -0
  14. data/lib/eclaircir/api_models/base_model.rb +11 -0
  15. data/lib/eclaircir/api_models/concept.rb +12 -0
  16. data/lib/eclaircir/api_models/data.rb +17 -0
  17. data/lib/eclaircir/api_models/input.rb +22 -0
  18. data/lib/eclaircir/api_models/media.rb +9 -0
  19. data/lib/eclaircir/api_models/model.rb +29 -0
  20. data/lib/eclaircir/api_models/output.rb +14 -0
  21. data/lib/eclaircir/api_models/response.rb +16 -0
  22. data/lib/eclaircir/api_models/status.rb +46 -0
  23. data/lib/eclaircir/api_models.rb +16 -0
  24. data/lib/eclaircir/client/status_validator.rb +30 -0
  25. data/lib/eclaircir/client.rb +85 -0
  26. data/lib/eclaircir/configuration.rb +16 -0
  27. data/lib/eclaircir/constants.rb +5 -0
  28. data/lib/eclaircir/error.rb +27 -0
  29. data/lib/eclaircir/version.rb +5 -0
  30. data/lib/eclaircir.rb +32 -0
  31. data/spec/eclaircir/api_models/concept_spec.rb +32 -0
  32. data/spec/eclaircir/api_models/data_spec.rb +104 -0
  33. data/spec/eclaircir/api_models/input_spec.rb +70 -0
  34. data/spec/eclaircir/api_models/media_spec.rb +15 -0
  35. data/spec/eclaircir/api_models/model_spec.rb +109 -0
  36. data/spec/eclaircir/api_models/output_spec.rb +42 -0
  37. data/spec/eclaircir/api_models/response_spec.rb +63 -0
  38. data/spec/eclaircir/api_models/status_spec.rb +67 -0
  39. data/spec/eclaircir/client/status_validator_spec.rb +77 -0
  40. data/spec/eclaircir/client_spec.rb +123 -0
  41. data/spec/eclaircir/configuration_spec.rb +64 -0
  42. data/spec/eclaircir_spec.rb +55 -0
  43. data/spec/etc/fixtures/predict_outputs/invalid_request.json +7 -0
  44. data/spec/etc/fixtures/predict_outputs/success.json +58 -0
  45. data/spec/factories/concept.rb +8 -0
  46. data/spec/factories/data.rb +13 -0
  47. data/spec/factories/input.rb +7 -0
  48. data/spec/factories/media.rb +6 -0
  49. data/spec/factories/model.rb +9 -0
  50. data/spec/factories/response.rb +7 -0
  51. data/spec/factories/status.rb +7 -0
  52. data/spec/spec_helper.rb +53 -0
  53. metadata +122 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 82949b54ab4bb6cf95d31e2a463792c865412137
4
+ data.tar.gz: 84da4238a63460cf6c0b1d92502462586c2de59d
5
+ SHA512:
6
+ metadata.gz: 0493fe176bba3a735e5bb5b3b1b533bd617334657519d74a567215ae496f5961a0d455ea8000a49d789c3380b5c0cfc65a0e49bc66409749d37b6d0dfa632c8c
7
+ data.tar.gz: c7a7831b5afb741d095305ec90fdda0d502204525aa60e0c2b71a16e2dbbb6fc6209c0db2dd30d00a9f9dda7496b12aebc65cd26083c2fdaf98f13aa83c0c5ed
data/.gitignore ADDED
@@ -0,0 +1,27 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile ~/.gitignore_global
6
+
7
+ # Ignore bundler config
8
+ /.bundle
9
+
10
+ # Ignore all logfiles and tempfiles.
11
+ /log/*.log
12
+ /tmp
13
+ /coverage
14
+ /public
15
+ /debug
16
+ /.bundle
17
+ /doc
18
+ /db/schema.rb
19
+
20
+ # Ignore dotenv config
21
+ /.env
22
+
23
+ # Ignore rspec customization
24
+ /.rspec
25
+
26
+ # Ignore Gemfile.lock as this is a gem
27
+ /Gemfile.lock
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ bundler_args: --jobs=2
3
+ before_install: gem install bundler
4
+ script: 'bundle exec rake spec'
5
+ rvm:
6
+ - 2.4.0
7
+ - 2.3.0
8
+ - 2.2.0
9
+ - 2.1.0
10
+ - 2.0.0
11
+ cache: bundler
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ gem 'rake'
5
+ gem 'virtus'
6
+
7
+ group :test, :development do
8
+ gem 'rspec', '~> 3.4'
9
+ gem 'rspec-its'
10
+ gem 'byebug'
11
+ gem 'dotenv'
12
+ gem 'simplecov', require: false
13
+ gem 'coveralls', require: false
14
+ gem 'factory_bot'
15
+ gem 'faker'
16
+ gem 'webmock'
17
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Karim Bogtob
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # Eclaircir
2
+ Eclaircir is a french synonym for 'Clarify' and seemed relevant as a name for the gem.
3
+
4
+ This gem aims to be a Clarifai APIv2 wrapper that is complete, tested and covered.
5
+
6
+ [![Build Status](https://travis-ci.org/kbogtob/eclaircir.svg?branch=master)](https://travis-ci.org/kbogtob/eclaircir)
7
+ [![Coverage Status](https://coveralls.io/repos/github/kbogtob/eclaircir/badge.svg?branch=master)](https://coveralls.io/github/kbogtob/eclaircir?branch=master)
8
+
9
+ ## Install
10
+
11
+ ```sh
12
+ gem install eclaircir
13
+ ```
14
+
15
+ ## Requirements
16
+ * Ruby 2.0.0 or higher
17
+ * HTTParty
18
+ * Virtus
19
+
20
+ ## Examples
21
+
22
+ ...
23
+
24
+ ## Contributing
25
+ * Fork the project
26
+ * Run `bundle install --path .bundle`
27
+ * Run `bundle exec rake spec`
28
+ * Add tests for your feature (the TDD way!)
29
+ * Implement your feature
30
+ * Run tests again
31
+ * Commit (excluding the `Rakefile` or the `Version.rb` if you want to be merged)
32
+ * Send a pull request
33
+
34
+ ## How can I help?
35
+
36
+ The Roadmap for V1 is to provide a completely usable API wrapper to do common tasks on Clarifai.
37
+
38
+ Here's an extract from the TODO:
39
+
40
+ # V1.0
41
+ - [x] Authentication
42
+ - [x] API Key Management
43
+ - [x] Authorization
44
+ - [x] Status Management
45
+ - [x] Modelization: Response
46
+ - [x] Modelization: Status
47
+ - [x] Modelization: Output
48
+ - [x] General Errors
49
+ - [x] Specific Errors
50
+ - [ ] Fully manage statuses using the statuses cheatsheet
51
+ - [x] Response Parsing
52
+ - [x] Predict
53
+ - [x] Modelization: Input
54
+ - [x] Modelization: Data
55
+ - [x] Modelization: Concept
56
+ - [x] Modelization: Model
57
+ - [x] Support URL Requests for Images
58
+ - [x] Response Parsing
59
+ - [ ] Support base 64 Requests for Images
60
+ - [ ] Support of multiple inputs (max 128)
61
+ - [ ] Modelization: Frame
62
+ - [ ] Video support
63
+ - [ ] Search
64
+ - [ ] Add Images to search index
65
+ - [ ] Search by concept
66
+ - [ ] Search by image
67
+ - [ ] Train
68
+ - [ ] Add image with concepts
69
+ - [ ] Model Creation
70
+ - [ ] Model Training
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler'
4
+
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ task default: :spec
8
+
9
+ require 'rspec/core/rake_task'
10
+ RSpec::Core::RakeTask.new do |t|
11
+ t.rspec_opts = ["--color", '--format doc']
12
+ end
data/TODO.md ADDED
@@ -0,0 +1,75 @@
1
+ # V1.0
2
+ - [x] Authentication
3
+ - [x] API Key Management
4
+ - [x] Authorization
5
+ - [x] Status Management
6
+ - [x] Modelization: Response
7
+ - [x] Modelization: Status
8
+ - [x] Modelization: Output
9
+ - [x] General Errors
10
+ - [x] Specific Errors
11
+ - [ ] Fully manage statuses using the statuses cheatsheet
12
+ - [x] Response Parsing
13
+ - [x] Predict
14
+ - [x] Modelization: Input
15
+ - [x] Modelization: Data
16
+ - [x] Modelization: Concept
17
+ - [x] Modelization: Model
18
+ - [x] Support URL Requests for Images
19
+ - [x] Response Parsing
20
+ - [ ] Support base 64 Requests for Images
21
+ - [ ] Support of multiple inputs (max 128)
22
+ - [ ] Modelization: Frame
23
+ - [ ] Video support
24
+ - [ ] Search
25
+ - [ ] Add Images to search index
26
+ - [ ] Search by concept
27
+ - [ ] Search by image
28
+ - [ ] Train
29
+ - [ ] Add image with concepts
30
+ - [ ] Model Creation
31
+ - [ ] Model Training
32
+
33
+ # V2.0
34
+ - [ ] Feedback
35
+ - [ ] Modelization : Feedback Info
36
+ - [ ] Provide feedback on inputs with concepts
37
+ - [ ] Provide feedback on inputs with regions
38
+ - [ ] Provide feedback on searches
39
+ - [ ] Inputs management
40
+ - [ ] Add input with custom id
41
+ - [ ] Add input with metadata
42
+ - [ ] Add input with crop
43
+ - [ ] Get input by id
44
+ - [ ] Modelization: Status
45
+ - [ ] Get input status
46
+ - [ ] Input: Upsert concepts
47
+ - [ ] Input: Delete concepts
48
+ - [ ] Input: Bulk Upsert concepts
49
+ - [ ] Input: Bulk Delete concepts
50
+ - [ ] Delete input
51
+ - [ ] Bulk Delete input
52
+ - [ ] Clean inputs
53
+ - [ ] Models management
54
+ - [ ] Create model with concepts
55
+ - [ ] Model: Upsert concepts
56
+ - [ ] Model: Delete concepts
57
+ - [ ] Model: Update concept name
58
+ - [ ] List models
59
+ - [ ] Get model by id
60
+ - [ ] Model: List concepts
61
+ - [ ] Model: List versions
62
+ - [ ] Model: Get version by id
63
+ - [ ] Model: Get training inputs
64
+ - [ ] Model: Get training inputs by version
65
+ - [ ] Delete model
66
+ - [ ] Model: Delete version
67
+ - [ ] Clean models
68
+ - [ ] Search model
69
+
70
+ - [ ] Workflow Predict
71
+
72
+ # Experimental features
73
+ - [ ] Video splitting using ffmpeg
74
+ - [ ] For models not supporting videos
75
+ - [ ] For videos too big
data/bin/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ begin
5
+ require 'dotenv'
6
+ Dotenv.load
7
+ rescue LoadError
8
+ end
9
+
10
+ exec('irb', '-I', 'lib/', '-r', 'eclaircir')
data/bin/test.rb ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+
6
+ require 'eclaircir'
7
+ require 'byebug'
8
+
9
+ c = Eclaircir::Client.new(Eclaircir.configuration.api_key)
10
+
11
+ input = Eclaircir::Input.from_url('https://samples.clarifai.com/metro-north.jpg')
12
+ model = Eclaircir::Model.new(id: 'aaa03c23b3724a16a56b629203edc62c')
13
+ # response = model.predict_outputs(url: 'https://samples.clarifai.com/metro-north.jpg')
14
+ response = model.predict_outputs(input: input)
15
+
16
+ # response = c.predict_outputs(model, input)
17
+ puts response.inspect
data/eclaircir.gemspec ADDED
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'lib/eclaircir/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'eclaircir'
8
+ s.version = Eclaircir::VERSION
9
+ s.summary = 'Clarifai APIv2 Client'
10
+ s.description = 'Ruby Clarifai API wrapper that aims to be complete, tested and covered'
11
+ s.authors = ['Karim Bogtob']
12
+ s.email = 'kabogtob@gmail.com'
13
+ s.homepage = 'https://github.com/kbogtob/eclaircir'
14
+ s.license = 'MIT'
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+
18
+ s.add_dependency 'httparty', ['~> 0.14.0']
19
+ s.add_dependency 'virtus', ['~> 1.0']
20
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Eclaircir
4
+ module Attributes
5
+ class NullableDateTime < Virtus::Attribute
6
+ def coerce(value)
7
+ if value.nil? || value.is_a?(DateTime)
8
+ value
9
+ else
10
+ DateTime.parse(value)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Eclaircir
4
+ module Attributes
5
+ end
6
+ end
7
+
8
+ require_relative 'attributes/nullable_date_time'
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Eclaircir
4
+ class BaseModel
5
+ include Virtus.model
6
+
7
+ def to_api_hash
8
+ attributes
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_model'
4
+
5
+ module Eclaircir
6
+ class Concept < BaseModel
7
+ attribute :id, String
8
+ attribute :name, String
9
+ attribute :app_id, String
10
+ attribute :value, Float
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_model'
4
+
5
+ module Eclaircir
6
+ class Data < BaseModel
7
+ attribute :image, Media
8
+ attribute :concepts, Array[Concept]
9
+
10
+ def to_api_hash
11
+ super.tap do |api_hash|
12
+ api_hash[:image] = image.to_api_hash if image
13
+ api_hash[:concepts] = concepts.map(&:to_api_hash) if concepts
14
+ end.compact
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_model'
4
+
5
+ module Eclaircir
6
+ class Input < BaseModel
7
+ attribute :id, String
8
+ attribute :data, Data
9
+
10
+ class << self
11
+ def from_url(url)
12
+ self.new(
13
+ data: Data.new(
14
+ image: Media.new(url: url)))
15
+ end
16
+ end
17
+
18
+ def to_api_hash
19
+ super.merge(data: data.to_api_hash).compact
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_model'
4
+
5
+ module Eclaircir
6
+ class Media < BaseModel
7
+ attribute :url, String
8
+ end
9
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_model'
4
+
5
+ module Eclaircir
6
+ class Model < BaseModel
7
+ attribute :id, String
8
+ attribute :name, String
9
+ attribute :created_at, Attributes::NullableDateTime
10
+ attribute :app_id, String
11
+ attribute :output_info, Hash
12
+ attribute :model_version, Hash
13
+
14
+ def predict_outputs(url: nil, input: nil)
15
+ to_predict = if url
16
+ Input.from_url(url)
17
+ elsif input
18
+ input
19
+ end
20
+
21
+ if Array(to_predict).empty?
22
+ raise ArgumentError,
23
+ 'one of the following keyword arguments should be provided [url, input]'
24
+ end
25
+
26
+ Eclaircir.new_client.predict_outputs(self, to_predict)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_model'
4
+
5
+ module Eclaircir
6
+ class Output < BaseModel
7
+ attribute :id, String
8
+ attribute :status, Status
9
+ attribute :created_at, Attributes::NullableDateTime
10
+ attribute :model, Model
11
+ attribute :input, Input
12
+ attribute :data, Data
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_model'
4
+
5
+ module Eclaircir
6
+ class Response < BaseModel
7
+ attribute :status, Status
8
+ attribute :outputs, Array[Output]
9
+
10
+ class << self
11
+ def parse(raw_response)
12
+ self.new(raw_response)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_model'
4
+
5
+ module Eclaircir
6
+ class Status < BaseModel
7
+ attribute :code, Integer
8
+ attribute :description, String
9
+
10
+ def success?
11
+ code == SUCCESS
12
+ end
13
+
14
+ def validate!
15
+ unless success?
16
+ error_class = ERRORS_MAPPINGS.fetch(code, APIError)
17
+ raise error_class, description
18
+ end
19
+
20
+ true
21
+ end
22
+
23
+ # statuses
24
+ SUCCESS = 10_000
25
+
26
+ FAILURE = 10_020
27
+
28
+ INVALID_AUTH_TOKEN = 11_001
29
+ API_KEY_NOT_FOUND = 11_009
30
+
31
+ BAD_REQUEST_FORMAT = 11_100
32
+ INVALID_REQUEST = 11_102
33
+
34
+ DUPLICATE_URL = 30_100
35
+ IMAGE_DECODING_FAILED = 30_300
36
+
37
+ ERRORS_MAPPINGS = {
38
+ INVALID_AUTH_TOKEN => InvalidAuthTokenError,
39
+ API_KEY_NOT_FOUND => ApiKeyNotFoundError,
40
+ BAD_REQUEST_FORMAT => BadRequestFormatError,
41
+ INVALID_REQUEST => InvalidRequestError,
42
+ DUPLICATE_URL => DuplicateURLError,
43
+ IMAGE_DECODING_FAILED => ImageDecodingError,
44
+ }.freeze
45
+ end
46
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Eclaircir
4
+
5
+ end
6
+
7
+ require_relative 'api_models/attributes'
8
+
9
+ require_relative 'api_models/concept'
10
+ require_relative 'api_models/status'
11
+ require_relative 'api_models/media'
12
+ require_relative 'api_models/data'
13
+ require_relative 'api_models/model'
14
+ require_relative 'api_models/input'
15
+ require_relative 'api_models/output'
16
+ require_relative 'api_models/response'
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Eclaircir
4
+ class Client
5
+ class StatusValidator
6
+ def initialize(response)
7
+ @response = response
8
+ end
9
+
10
+ def validate!
11
+ return true if main_status.success?
12
+
13
+ sub_statuses.each(&:validate!)
14
+
15
+ main_status.validate!
16
+ end
17
+
18
+ protected
19
+ attr_reader :response
20
+
21
+ def main_status
22
+ response.status
23
+ end
24
+
25
+ def sub_statuses
26
+ response.outputs.map(&:status)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Eclaircir
4
+ class Client
5
+ include HTTParty
6
+
7
+ base_uri(Eclaircir::API_ENDPOINT)
8
+ format :json
9
+ headers 'Content-Type' => 'application/json', 'Accept' => 'application/json'
10
+
11
+ def initialize(api_key)
12
+ @api_key = api_key
13
+ end
14
+
15
+ def models(options = {})
16
+ get('/models', query: options)
17
+ end
18
+
19
+ def predict_outputs(model, inputs)
20
+ with_response_parsing do
21
+ validate post("/models/#{model.id}/outputs", body: {
22
+ inputs: Array(inputs).map(&:to_api_hash)
23
+ }.to_json)
24
+ end
25
+ end
26
+
27
+ protected
28
+ attr_reader :api_key
29
+
30
+ def authorization_headers
31
+ @authorization_headers ||= {
32
+ 'Authorization' => "Key #{api_key}"
33
+ }
34
+ end
35
+
36
+ def get(path, query: nil)
37
+ self.class.get(path,
38
+ headers: authorization_headers,
39
+ query: query)
40
+ end
41
+
42
+ def post(path, query: nil, body: nil)
43
+ self.class.post(path,
44
+ headers: authorization_headers,
45
+ query: query,
46
+ body: body)
47
+ end
48
+
49
+ def patch(path, query: nil, body: nil)
50
+ self.class.patch(path,
51
+ headers: authorization_headers,
52
+ query: query,
53
+ body: body)
54
+ end
55
+
56
+ def delete(path, query: nil, body: nil)
57
+ self.class.delete(path,
58
+ headers: authorization_headers,
59
+ query: query,
60
+ body: body)
61
+ end
62
+
63
+ def with_response_parsing
64
+ Eclaircir::Response.parse(yield).tap do |response|
65
+ StatusValidator.new(response).validate!
66
+ end
67
+ end
68
+
69
+ def validate(response)
70
+ case response.code
71
+ when 200..399
72
+ response.parsed_response
73
+ else
74
+ raise_status_error(response.parsed_response)
75
+ end
76
+ end
77
+
78
+ def raise_status_error(raw_response)
79
+ status = raw_response['status']
80
+ raise APIError, status['description']
81
+ end
82
+ end
83
+ end
84
+
85
+ require_relative 'client/status_validator'
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Eclaircir
4
+ class Configuration
5
+ def initialize(
6
+ env: ENV,
7
+ api_key: nil)
8
+ @api_key = api_key || env['CLARIFIER_API_KEY']
9
+ end
10
+
11
+ attr_accessor :api_key
12
+
13
+ protected
14
+ attr_reader :env
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Eclaircir
4
+ API_ENDPOINT = 'https://api.clarifai.com/v2'
5
+ end