scaleapi-ruby 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/CONTRIBUTING.md +29 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +121 -0
- data/LICENSE.md +25 -0
- data/README.md +237 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/lib/scale.rb +42 -0
- data/lib/scale/api.rb +104 -0
- data/lib/scale/callbacks/base.rb +25 -0
- data/lib/scale/callbacks/task.rb +23 -0
- data/lib/scale/endpoints/endpoint.rb +31 -0
- data/lib/scale/endpoints/tasks/cancel_task.rb +23 -0
- data/lib/scale/endpoints/tasks/create_annotation_task.rb +16 -0
- data/lib/scale/endpoints/tasks/create_categorization_task.rb +16 -0
- data/lib/scale/endpoints/tasks/create_comparison_task.rb +16 -0
- data/lib/scale/endpoints/tasks/create_phonecall_task.rb +16 -0
- data/lib/scale/endpoints/tasks/create_transcription_task.rb +16 -0
- data/lib/scale/endpoints/tasks/list_tasks.rb +27 -0
- data/lib/scale/endpoints/tasks/retrieve_task.rb +23 -0
- data/lib/scale/endpoints/tasks/task_endpoint.rb +22 -0
- data/lib/scale/generic_error.rb +4 -0
- data/lib/scale/http_error.rb +16 -0
- data/lib/scale/resources/base.rb +6 -0
- data/lib/scale/resources/task.rb +26 -0
- data/test/callbacks/test_task_callback.rb +35 -0
- data/test/fixtures/callback.json +29 -0
- data/test/fixtures/vcr_cassettes/tasks.yml +2629 -0
- data/test/helper.rb +42 -0
- data/test/tasks/test_cancel_task.rb +21 -0
- data/test/tasks/test_create_annotation_task.rb +40 -0
- data/test/tasks/test_create_categorization_task.rb +40 -0
- data/test/tasks/test_create_comparison_task.rb +43 -0
- data/test/tasks/test_create_phonecall_task.rb +41 -0
- data/test/tasks/test_create_transcription_task.rb +41 -0
- data/test/tasks/test_list_tasks.rb +14 -0
- data/test/tasks/test_retrieve_task.rb +37 -0
- data/test/test_api.rb +27 -0
- metadata +182 -0
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'juwelier'
|
15
|
+
Juwelier::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
|
17
|
+
gem.name = "scaleapi-ruby"
|
18
|
+
gem.homepage = "http://github.com/wikiti/scaleapi-ruby"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{A ruby gem wrapper for the Scale API}
|
21
|
+
gem.description = %Q{A ruby gem wrapper for the Scale API, containing all the endpoints available.}
|
22
|
+
gem.email = "info@danielherzog.es"
|
23
|
+
gem.authors = ["Daniel Herzog"]
|
24
|
+
|
25
|
+
# dependencies defined in Gemfile
|
26
|
+
end
|
27
|
+
Juwelier::RubygemsDotOrgTasks.new
|
28
|
+
|
29
|
+
require 'rake/testtask'
|
30
|
+
Rake::TestTask.new(:test) do |test|
|
31
|
+
test.libs << 'lib' << 'test'
|
32
|
+
test.pattern = 'test/**/test_*.rb'
|
33
|
+
test.verbose = true
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "Code coverage detail"
|
37
|
+
task :simplecov do
|
38
|
+
ENV['COVERAGE'] = "true"
|
39
|
+
Rake::Task['test'].execute
|
40
|
+
end
|
41
|
+
|
42
|
+
task :default => :test
|
43
|
+
|
44
|
+
require 'rdoc/task'
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
47
|
+
|
48
|
+
rdoc.rdoc_dir = 'rdoc'
|
49
|
+
rdoc.title = "scaleapi-ruby #{version}"
|
50
|
+
rdoc.rdoc_files.include('README*')
|
51
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
52
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/lib/scale.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'time'
|
3
|
+
require 'rest-client'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
7
|
+
|
8
|
+
require 'scale/api'
|
9
|
+
require 'scale/generic_error'
|
10
|
+
require 'scale/http_error'
|
11
|
+
|
12
|
+
require 'scale/resources/base'
|
13
|
+
require 'scale/resources/task'
|
14
|
+
|
15
|
+
require 'scale/endpoints/endpoint'
|
16
|
+
|
17
|
+
require 'scale/endpoints/tasks/task_endpoint'
|
18
|
+
require 'scale/endpoints/tasks/create_annotation_task'
|
19
|
+
require 'scale/endpoints/tasks/create_categorization_task'
|
20
|
+
require 'scale/endpoints/tasks/create_transcription_task'
|
21
|
+
require 'scale/endpoints/tasks/create_comparison_task'
|
22
|
+
require 'scale/endpoints/tasks/create_phonecall_task'
|
23
|
+
require 'scale/endpoints/tasks/retrieve_task'
|
24
|
+
require 'scale/endpoints/tasks/cancel_task'
|
25
|
+
require 'scale/endpoints/tasks/list_tasks'
|
26
|
+
|
27
|
+
require 'scale/callbacks/base'
|
28
|
+
require 'scale/callbacks/task'
|
29
|
+
|
30
|
+
module Scale
|
31
|
+
def self.setup(params = {})
|
32
|
+
Scale::API.new params
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.hash(data = nil)
|
36
|
+
ActiveSupport::HashWithIndifferentAccess.new data
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.descendants(klass)
|
40
|
+
ObjectSpace.each_object(::Class).select {|d| d < klass }
|
41
|
+
end
|
42
|
+
end
|
data/lib/scale/api.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
module Scale
|
2
|
+
class API
|
3
|
+
DEFAULT_PARAMS = {
|
4
|
+
endpoint: 'https://api.scaleapi.com/v1/',
|
5
|
+
default_request_params: {}
|
6
|
+
}.freeze
|
7
|
+
|
8
|
+
attr_reader :endpoint, :api_key, :callback_key, :default_request_params, :params
|
9
|
+
|
10
|
+
def initialize(params = {})
|
11
|
+
params = DEFAULT_PARAMS.merge params
|
12
|
+
|
13
|
+
@params = Scale.hash(params)
|
14
|
+
@endpoint = fetch_attribute :endpoint
|
15
|
+
@api_key = fetch_attribute :api_key
|
16
|
+
@callback_key = fetch_attribute :callback_key
|
17
|
+
@default_request_params = fetch_attribute :default_request_params
|
18
|
+
|
19
|
+
validate!
|
20
|
+
end
|
21
|
+
|
22
|
+
def request(type, path, payload = {})
|
23
|
+
RestClient::Request.new(
|
24
|
+
method: type,
|
25
|
+
url: url(path),
|
26
|
+
user: api_key,
|
27
|
+
payload: Scale.hash(default_request_params).merge(Scale.hash(payload)),
|
28
|
+
headers: { accept: :json, content_type: :json }
|
29
|
+
).execute
|
30
|
+
rescue RestClient::Exception => e
|
31
|
+
raise HttpError, e
|
32
|
+
end
|
33
|
+
|
34
|
+
def build_callback(data, type = 'task', options = {})
|
35
|
+
options = Scale.hash options
|
36
|
+
matchers = Scale.descendants(Scale::Callbacks::Base)
|
37
|
+
klass = matchers.find { |c| c.match? type }
|
38
|
+
|
39
|
+
validate_callback_handler! klass
|
40
|
+
validate_callback_token! options[:callback_key]
|
41
|
+
|
42
|
+
klass.new data
|
43
|
+
end
|
44
|
+
|
45
|
+
def valid_callback_key?(key)
|
46
|
+
key.to_s == callback_key.to_s
|
47
|
+
end
|
48
|
+
|
49
|
+
# Endpoint helper. If the method is not defined, then try looking into the available endpoints.
|
50
|
+
def method_missing(m, *array)
|
51
|
+
endpoint = Scale.descendants(Scale::Endpoints::Endpoint).find { |e| e.match? m }
|
52
|
+
return endpoint.new(self, *array).process if endpoint
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
def validate!
|
59
|
+
validate_endpoint!
|
60
|
+
validate_api_key!
|
61
|
+
validate_callback_key!
|
62
|
+
end
|
63
|
+
|
64
|
+
def fetch_attribute(name)
|
65
|
+
params[name] || send(name)
|
66
|
+
end
|
67
|
+
|
68
|
+
def url(path)
|
69
|
+
"#{endpoint.end_with?('/') ? endpoint : endpoint + '/'}#{path}"
|
70
|
+
end
|
71
|
+
|
72
|
+
# -------------------
|
73
|
+
# Validators
|
74
|
+
# -------------------
|
75
|
+
|
76
|
+
def validate_callback_handler!(klass)
|
77
|
+
raise GenericError, "Callback handler '#{name}' not found. Try #{matchers.map(&:shortcut).join ','}" unless klass
|
78
|
+
end
|
79
|
+
|
80
|
+
def validate_callback_token!(key)
|
81
|
+
return if callback_key.nil?
|
82
|
+
raise GenericError, "Invalid HTTP callback with key #{key}" unless valid_callback_key? key
|
83
|
+
end
|
84
|
+
|
85
|
+
def validate_callback_key!
|
86
|
+
return if callback_key.nil?
|
87
|
+
raise GenericError, invalid_attribute('callback_key') unless api_key.to_s != ''
|
88
|
+
end
|
89
|
+
|
90
|
+
def validate_endpoint!
|
91
|
+
valid = URI.parse "endpoint" rescue nil
|
92
|
+
raise GenericError, invalid_attribute('endpoint') unless valid
|
93
|
+
end
|
94
|
+
|
95
|
+
def validate_api_key!
|
96
|
+
raise GenericError, invalid_attribute('api_key') unless api_key.to_s != ''
|
97
|
+
end
|
98
|
+
|
99
|
+
def invalid_attribute(name)
|
100
|
+
"Invalid Scale API `#{name}`. Please, set a valid `#{name}` parameter"
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Scale
|
2
|
+
module Callbacks
|
3
|
+
class Base
|
4
|
+
attr_reader :response, :json
|
5
|
+
|
6
|
+
def initialize(data)
|
7
|
+
@json = Scale.hash(data)
|
8
|
+
@response = json[:response]
|
9
|
+
end
|
10
|
+
|
11
|
+
def status_code
|
12
|
+
response[:status_code]
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def self.shortcut
|
17
|
+
raise NotImplementedError
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.match?(method)
|
21
|
+
shortcut.to_s == method.to_s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Scale
|
2
|
+
module Callbacks
|
3
|
+
class Task < Base
|
4
|
+
attr_reader :task
|
5
|
+
|
6
|
+
def initialize(json)
|
7
|
+
super
|
8
|
+
build_task
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.shortcut
|
12
|
+
'task'
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def build_task
|
18
|
+
task_data = json[:task].merge task_id: json[:task_id]
|
19
|
+
@task = Scale::Resources::Task.new task_data
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Scale
|
2
|
+
module Endpoints
|
3
|
+
class Endpoint
|
4
|
+
attr_reader :api, :args, :params
|
5
|
+
|
6
|
+
def initialize(api, *args)
|
7
|
+
@api = api
|
8
|
+
@args = args
|
9
|
+
@params = Scale.hash(args.pop) if args.last.is_a?(Hash)
|
10
|
+
end
|
11
|
+
|
12
|
+
def process
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.shortcut
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.match?(method)
|
21
|
+
shortcut.to_s == method.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def fetch_param(name)
|
27
|
+
params[name.to_s] || params[name.to_sym]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Scale
|
2
|
+
module Endpoints
|
3
|
+
module Tasks
|
4
|
+
class CancelTask < TaskEndpoint
|
5
|
+
attr_reader :task_id
|
6
|
+
|
7
|
+
def initialize(api, *args)
|
8
|
+
super
|
9
|
+
@task_id = args.first
|
10
|
+
end
|
11
|
+
|
12
|
+
def process
|
13
|
+
response = api.request :post, path("#{task_id}/cancel")
|
14
|
+
build_task response
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.shortcut
|
18
|
+
'cancel_task'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Scale
|
2
|
+
module Endpoints
|
3
|
+
module Tasks
|
4
|
+
class CreateAnnotationTask < TaskEndpoint
|
5
|
+
def process
|
6
|
+
response = api.request :post, path('annotation'), params
|
7
|
+
build_task response
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.shortcut
|
11
|
+
'create_annotation_task'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Scale
|
2
|
+
module Endpoints
|
3
|
+
module Tasks
|
4
|
+
class CreateCategorizationTask < TaskEndpoint
|
5
|
+
def process
|
6
|
+
response = api.request :post, path('categorize'), params
|
7
|
+
build_task response
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.shortcut
|
11
|
+
'create_categorization_task'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Scale
|
2
|
+
module Endpoints
|
3
|
+
module Tasks
|
4
|
+
class CreateComparisonTask < TaskEndpoint
|
5
|
+
def process
|
6
|
+
response = api.request :post, path('comparison'), params
|
7
|
+
build_task response
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.shortcut
|
11
|
+
'create_comparison_task'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Scale
|
2
|
+
module Endpoints
|
3
|
+
module Tasks
|
4
|
+
class CreatePhonecallTask < TaskEndpoint
|
5
|
+
def process
|
6
|
+
response = api.request :post, path('phonecall'), params
|
7
|
+
build_task response
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.shortcut
|
11
|
+
'create_phonecall_task'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Scale
|
2
|
+
module Endpoints
|
3
|
+
module Tasks
|
4
|
+
class CreateTranscriptionTask < TaskEndpoint
|
5
|
+
def process
|
6
|
+
response = api.request :post, path('transcription'), params
|
7
|
+
build_task response
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.shortcut
|
11
|
+
'create_transcription_task'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Scale
|
2
|
+
module Endpoints
|
3
|
+
module Tasks
|
4
|
+
class ListTasks < TaskEndpoint
|
5
|
+
def process
|
6
|
+
response = api.request :get, path
|
7
|
+
build_tasks response
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.shortcut
|
11
|
+
'tasks'
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
def path
|
17
|
+
"tasks"
|
18
|
+
end
|
19
|
+
|
20
|
+
def build_tasks(response)
|
21
|
+
response = parse(response)
|
22
|
+
response.map { |obj| build_task obj }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Scale
|
2
|
+
module Endpoints
|
3
|
+
module Tasks
|
4
|
+
class RetrieveTask < TaskEndpoint
|
5
|
+
attr_reader :task_id
|
6
|
+
|
7
|
+
def initialize(api, *args)
|
8
|
+
super
|
9
|
+
@task_id = args.first
|
10
|
+
end
|
11
|
+
|
12
|
+
def process
|
13
|
+
response = api.request :get, path(task_id)
|
14
|
+
build_task response
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.shortcut
|
18
|
+
'retrieve_task'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|