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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/CONTRIBUTING.md +29 -0
  4. data/Gemfile +19 -0
  5. data/Gemfile.lock +121 -0
  6. data/LICENSE.md +25 -0
  7. data/README.md +237 -0
  8. data/Rakefile +52 -0
  9. data/VERSION +1 -0
  10. data/lib/scale.rb +42 -0
  11. data/lib/scale/api.rb +104 -0
  12. data/lib/scale/callbacks/base.rb +25 -0
  13. data/lib/scale/callbacks/task.rb +23 -0
  14. data/lib/scale/endpoints/endpoint.rb +31 -0
  15. data/lib/scale/endpoints/tasks/cancel_task.rb +23 -0
  16. data/lib/scale/endpoints/tasks/create_annotation_task.rb +16 -0
  17. data/lib/scale/endpoints/tasks/create_categorization_task.rb +16 -0
  18. data/lib/scale/endpoints/tasks/create_comparison_task.rb +16 -0
  19. data/lib/scale/endpoints/tasks/create_phonecall_task.rb +16 -0
  20. data/lib/scale/endpoints/tasks/create_transcription_task.rb +16 -0
  21. data/lib/scale/endpoints/tasks/list_tasks.rb +27 -0
  22. data/lib/scale/endpoints/tasks/retrieve_task.rb +23 -0
  23. data/lib/scale/endpoints/tasks/task_endpoint.rb +22 -0
  24. data/lib/scale/generic_error.rb +4 -0
  25. data/lib/scale/http_error.rb +16 -0
  26. data/lib/scale/resources/base.rb +6 -0
  27. data/lib/scale/resources/task.rb +26 -0
  28. data/test/callbacks/test_task_callback.rb +35 -0
  29. data/test/fixtures/callback.json +29 -0
  30. data/test/fixtures/vcr_cassettes/tasks.yml +2629 -0
  31. data/test/helper.rb +42 -0
  32. data/test/tasks/test_cancel_task.rb +21 -0
  33. data/test/tasks/test_create_annotation_task.rb +40 -0
  34. data/test/tasks/test_create_categorization_task.rb +40 -0
  35. data/test/tasks/test_create_comparison_task.rb +43 -0
  36. data/test/tasks/test_create_phonecall_task.rb +41 -0
  37. data/test/tasks/test_create_transcription_task.rb +41 -0
  38. data/test/tasks/test_list_tasks.rb +14 -0
  39. data/test/tasks/test_retrieve_task.rb +37 -0
  40. data/test/test_api.rb +27 -0
  41. 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