smooth_operator 0.0.2 → 0.3.2

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.
@@ -3,4 +3,6 @@ module SmoothOperator
3
3
  end
4
4
 
5
5
  require "smooth_operator/version"
6
+ require "smooth_operator/core"
6
7
  require "smooth_operator/base"
8
+ require "smooth_operator/rollback"
@@ -1,62 +1,30 @@
1
- require "smooth_operator/operator"
2
- require "smooth_operator/orm"
1
+ require "smooth_operator/operator/base"
2
+ require "smooth_operator/operator/orm"
3
3
 
4
- module SmoothOperator
5
- class Base < OpenStruct
6
-
7
- include SmoothOperator::Operator
8
- include SmoothOperator::ORM
9
-
10
- def hash_of_full_content
11
- @table
12
- end
13
-
14
- def as_json(options = nil)
15
- @table.as_json(options)
16
- end
17
-
18
- def self.nested_objects_classes(hash)
19
- hash.each do |nested_object_symbol, nested_object_class|
20
- define_method(nested_object_symbol.to_s) do
21
- get_nested_object_variable(nested_object_symbol, nested_object_class)
22
- end
23
- end
24
- end
4
+ require "smooth_operator/http_handlers/typhoeus/base"
5
+ require "smooth_operator/http_handlers/typhoeus/orm"
25
6
 
26
- private #---------------------------- private
27
-
28
- def get_nested_object_variable(nested_object_symbol, nested_object_class)
29
- nested_object_variable = instance_variable_get("@#{nested_object_symbol}")
30
-
31
- return nested_object_variable if nested_object_variable.present?
32
-
33
- nested_object_variable = initialize_nested_object_variable(hash_of_full_content[nested_object_symbol], nested_object_class, nested_object_symbol)
7
+ module SmoothOperator
34
8
 
35
- instance_variable_set("@#{nested_object_symbol}", nested_object_variable)
9
+ class Base < OpenStruct
10
+ include SmoothOperator::Core
11
+ include SmoothOperator::Operator::Base
12
+ include SmoothOperator::Operator::ORM
36
13
 
37
- nested_object_variable
38
- end
14
+ protected ################### PROTECTED ###################
39
15
 
40
- def initialize_nested_object_variable(attributes, nested_object_class, nested_object_symbol)
41
- if attributes.kind_of? Array
42
- attributes.map { |_attributes| get_nested_object(_attributes, nested_object_class, nested_object_symbol) }
43
- else
44
- get_nested_object(attributes, nested_object_class, nested_object_symbol)
45
- end
16
+ def self.http_handler_base
17
+ SmoothOperator::HttpHandlers::Typhoeus::Base
46
18
  end
47
19
 
48
- def get_nested_object(nested_objects_attributes, nested_object_class, nested_object_symbol)
49
- if nested_objects_attributes.blank?
50
- plural?(nested_object_symbol) ? [] : nil
51
- else
52
- nested_object_class.new(nested_objects_attributes)
53
- end
20
+ def self.http_handler_orm
21
+ @http_handler_orm ||= SmoothOperator::HttpHandlers::Typhoeus::ORM.new(self)
54
22
  end
55
23
 
56
- def plural?(string)
57
- string = string.to_s
58
- string == string.pluralize
24
+ def http_handler_orm
25
+ self.class.http_handler_orm
59
26
  end
60
27
 
61
28
  end
29
+
62
30
  end
@@ -0,0 +1,162 @@
1
+ module SmoothOperator
2
+ module Core
3
+
4
+ def table_hash
5
+ @table
6
+ end
7
+
8
+ def as_json(options = nil)
9
+ @table.as_json(options)
10
+ end
11
+
12
+ def new_record?
13
+ !persisted?
14
+ end
15
+
16
+ def persisted?
17
+ try(:id).present?
18
+ end
19
+
20
+ def to_partial_path
21
+ class_name_plural = self.class.table_name
22
+ "#{class_name_plural}/#{class_name_plural.singularize}"
23
+ end
24
+
25
+ def valid?
26
+ errors.blank?
27
+ end
28
+
29
+ def invalid?
30
+ !valid?
31
+ end
32
+
33
+ def assign_attributes(attributes = {})
34
+ return if attributes.blank?
35
+
36
+ attributes.each do |name, value|
37
+ send("#{name}=", value)
38
+ end
39
+ end
40
+
41
+ def safe_table_hash
42
+ safe_hash = table_hash.dup
43
+
44
+ if self.class.save_attr_white_list.present?
45
+ safe_hash.slice!(*self.class.save_attr_white_list)
46
+ else
47
+ self.class.save_attr_black_list.each { |attribute| safe_hash.delete(attribute) }
48
+ end
49
+
50
+ safe_hash
51
+ end
52
+
53
+
54
+ private ######################### PRIVATE ###############################
55
+
56
+ def get_nested_object_variable(nested_object_symbol, nested_object_class)
57
+ nested_object_variable = instance_variable_get("@#{nested_object_symbol}")
58
+
59
+ return nested_object_variable if nested_object_variable.present?
60
+
61
+ nested_object_variable = initialize_nested_object_variable(table_hash[nested_object_symbol], nested_object_class, nested_object_symbol)
62
+
63
+ instance_variable_set("@#{nested_object_symbol}", nested_object_variable)
64
+
65
+ nested_object_variable
66
+ end
67
+
68
+ def initialize_nested_object_variable(attributes, nested_object_class, nested_object_symbol)
69
+ if attributes.kind_of? Array
70
+ attributes.map { |_attributes| get_nested_object(_attributes, nested_object_class, nested_object_symbol) }
71
+ else
72
+ get_nested_object(attributes, nested_object_class, nested_object_symbol)
73
+ end
74
+ end
75
+
76
+ def get_nested_object(nested_objects_attributes, nested_object_class, nested_object_symbol)
77
+ if nested_objects_attributes.blank?
78
+ plural?(nested_object_symbol) ? [] : nil
79
+ else
80
+ nested_object_class.new(nested_objects_attributes)
81
+ end
82
+ end
83
+
84
+ def plural?(string)
85
+ string = string.to_s
86
+ string == string.pluralize
87
+ end
88
+
89
+
90
+ def self.included(base)
91
+ base.extend(ClassMethods)
92
+ end
93
+
94
+ module ClassMethods
95
+
96
+ def nested_objects_classes(hash)
97
+ hash.each do |nested_object_symbol, nested_object_class|
98
+ define_method(nested_object_symbol.to_s) do
99
+ get_nested_object_variable(nested_object_symbol, nested_object_class)
100
+ end
101
+ end
102
+ end
103
+
104
+ attr_writer :endpoint
105
+ def endpoint
106
+ @endpoint ||= ENV["API_ENDPOINT"]
107
+ end
108
+
109
+ attr_writer :endpoint_user
110
+ def endpoint_user
111
+ @endpoint_user ||= ENV["API_USER"]
112
+ end
113
+
114
+ attr_writer :endpoint_pass
115
+ def endpoint_pass
116
+ @endpoint_pass ||= ENV["API_PASS"]
117
+ end
118
+
119
+ attr_writer :save_attr_black_list
120
+ def save_attr_black_list
121
+ @save_attr_black_list ||= [:id, :created_at, :updated_at, :errors]
122
+ end
123
+
124
+ attr_writer :save_attr_white_list
125
+ def save_attr_white_list
126
+ @save_attr_white_list ||= []
127
+ end
128
+
129
+ attr_writer :model_name
130
+ def model_name
131
+ @model_name ||= name.split('::').last.underscore.capitalize
132
+ end
133
+
134
+ def model_name_downcase
135
+ model_name.downcase
136
+ end
137
+
138
+ attr_writer :table_name
139
+ def table_name
140
+ @table_name ||= model_name_downcase.to_s.pluralize
141
+ end
142
+
143
+ private ################################ PRIVATE #########################
144
+
145
+ def build_url(relative_path)
146
+ slash = '/' if relative_path.present?
147
+ extention = '.json'
148
+ [endpoint, table_name, slash, relative_path.to_s, extention].join
149
+ end
150
+
151
+ def get_basic_auth_credentials
152
+ if endpoint_user.present? || endpoint_pass.present?
153
+ { username: endpoint_user, password: endpoint_pass }
154
+ else
155
+ nil
156
+ end
157
+ end
158
+
159
+ end
160
+
161
+ end
162
+ end
@@ -0,0 +1,58 @@
1
+ require 'typhoeus'
2
+ require "smooth_operator/http_handlers/typhoeus/remote_call"
3
+
4
+ module SmoothOperator
5
+ module HttpHandlers
6
+ module Typhoeus
7
+
8
+ class Base
9
+
10
+ def self.make_the_call(http_verb, url, options, basic_auth_credentials)
11
+ hydra = get_hydra_and_remove_it_from options
12
+ options = { params: options, method: http_verb }.merge auth_credentials(basic_auth_credentials)
13
+
14
+ if hydra.present?
15
+ make_asynchronous_request(url, options, hydra)
16
+ else
17
+ make_synchronous_request(url, options)
18
+ end
19
+ end
20
+
21
+ private ###################### PRIVATE ##################
22
+
23
+ def self.auth_credentials(basic_auth_credentials)
24
+ basic_auth_credentials.blank? ? {} : { userpwd: "#{basic_auth_credentials[:username]}:#{basic_auth_credentials[:password]}" }
25
+ end
26
+
27
+ def self.get_hydra_and_remove_it_from(options)
28
+ options.delete(:hydra)
29
+ end
30
+
31
+ def self.make_synchronous_request(url, options)
32
+ request = ::Typhoeus::Request.new(url, options)
33
+ remote_call = SmoothOperator::HttpHandlers::Typhoeus::RemoteCall.new(request)
34
+
35
+ request.on_complete do |response|
36
+ remote_call.raw_response = response
37
+ remote_call.response = remote_call.parsed_response
38
+ end
39
+
40
+ request.run
41
+ remote_call
42
+ end
43
+
44
+ def self.make_asynchronous_request(url, options, hydra)
45
+ request = ::Typhoeus::Request.new(url, options)
46
+
47
+ remote_call = SmoothOperator::HttpHandlers::Typhoeus::RemoteCall.new(request)
48
+
49
+ hydra.queue(request)
50
+
51
+ remote_call
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,33 @@
1
+ module SmoothOperator
2
+ module HttpHandlers
3
+ module Typhoeus
4
+
5
+ class ORM
6
+
7
+ attr_reader :object_class
8
+
9
+ def initialize(object_class)
10
+ @object_class = object_class
11
+ end
12
+
13
+ def make_the_call(http_verb, options, id, &block)
14
+ injected_hydra = options[:hydra]
15
+ options[:hydra] = injected_hydra || ::Typhoeus::Hydra.hydra
16
+
17
+ remote_call = @object_class.make_the_call(http_verb, id, options)
18
+
19
+ remote_call.request.on_complete do |typhoeus_response|
20
+ remote_call.raw_response = typhoeus_response
21
+ yield(remote_call)
22
+ end
23
+
24
+ remote_call.request.run if injected_hydra.blank?
25
+
26
+ remote_call
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+ require "smooth_operator/operator/remote_call"
2
+
3
+ module SmoothOperator
4
+ module HttpHandlers
5
+ module Typhoeus
6
+
7
+ class RemoteCall < SmoothOperator::Operator::RemoteCall
8
+
9
+ attr_reader :request
10
+
11
+ def initialize(request)
12
+ @request = request
13
+ end
14
+
15
+ def parse_response
16
+ begin
17
+ @parse_response ||= ::HTTParty::Parser.call(@raw_response.body, :json)
18
+ rescue
19
+ nil
20
+ end
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,38 @@
1
+ module SmoothOperator
2
+ module Operator
3
+
4
+ module Base
5
+
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+
12
+ def get(relative_path, options = {})
13
+ make_the_call(:get, relative_path, options)
14
+ end
15
+
16
+ def post(relative_path, options = {})
17
+ make_the_call(:post, relative_path, options)
18
+ end
19
+
20
+ def put(relative_path, options = {})
21
+ make_the_call(:put, relative_path, options)
22
+ end
23
+
24
+ def delete(relative_path, options = {})
25
+ make_the_call(:delete, relative_path, options)
26
+ end
27
+
28
+ def make_the_call(http_verb, relative_path, options = {})
29
+ url = build_url(relative_path)
30
+ http_handler_base.make_the_call(http_verb, url, (options || {}), get_basic_auth_credentials)
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,64 @@
1
+ module SmoothOperator
2
+ module Operator
3
+
4
+ module Exceptions
5
+
6
+ extend self
7
+
8
+ def raise_proper_exception(response, code)
9
+ return nil if CODES_TO_IGNORE.include?(code)
10
+ exception_to_raise = (CODE_VS_EXCEPTIONS[code] || SmoothOperator::Operator::Exceptions::Unknown).new(response)
11
+ #raise exception_to_raise, exception_to_raise.message
12
+ end
13
+
14
+ class Base < StandardError
15
+ attr_reader :response
16
+
17
+ def initialize(response)
18
+ @response = response
19
+ end
20
+ end
21
+
22
+ class Unknown < SmoothOperator::Operator::Exceptions::Base
23
+ def message
24
+ 'Unknown Error'
25
+ end
26
+ end
27
+
28
+ class NotFound < SmoothOperator::Operator::Exceptions::Base
29
+ def message
30
+ 'NotFound'
31
+ end
32
+ end
33
+
34
+ class EntityNotProcessed < SmoothOperator::Operator::Exceptions::Base
35
+ def message
36
+ 'EntityNotProcessed'
37
+ end
38
+ end
39
+
40
+ class ServerError < SmoothOperator::Operator::Exceptions::Base
41
+ def message
42
+ 'ServerError'
43
+ end
44
+ end
45
+
46
+ class AuthorizationRequired < SmoothOperator::Operator::Exceptions::Base
47
+ def message
48
+ 'AuthorizationRequired'
49
+ end
50
+ end
51
+
52
+ CODES_TO_IGNORE = [200]
53
+
54
+ CODE_VS_EXCEPTIONS = {
55
+ 401 => AuthorizationRequired,
56
+ 422 => EntityNotProcessed,
57
+ 404 => NotFound,
58
+ 500 => ServerError
59
+ }
60
+
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,120 @@
1
+ module SmoothOperator
2
+ module Operator
3
+
4
+ module ORM
5
+
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ base.send(:attr_reader, :last_response)
9
+ base.send(:attr_reader, :exception)
10
+ end
11
+
12
+ module ClassMethods
13
+
14
+ def find(id, options = {})
15
+ if id == :all
16
+ find_each(options)
17
+ else
18
+ find_one(id, options)
19
+ end
20
+ end
21
+
22
+ def safe_find(id, options = {})
23
+ begin
24
+ find(id, options)
25
+ rescue Exception => exception #exception.response contains the server response
26
+ id == :all ? [] : nil
27
+ end
28
+ end
29
+
30
+ def create(options = {})
31
+ new_object = new(options)
32
+
33
+ http_handler_orm.make_the_call(:post, { model_name_downcase => new_object.safe_table_hash }, '') do |remote_call|
34
+ new_object.send('after_create_update_or_destroy', remote_call)
35
+ end
36
+
37
+ new_object
38
+ end
39
+
40
+ protected ####################### protected #######################
41
+
42
+ def find_each(options)
43
+ http_handler_orm.make_the_call(:get, options, '') do |remote_call|
44
+ objects_list = remote_call.get_attributes(table_name)
45
+
46
+ if objects_list.kind_of?(Array)
47
+ remote_call.response = objects_list.map { |attributes| new remote_call.get_attributes(model_name_downcase, attributes) }
48
+ else
49
+ remote_call.response = objects_list
50
+ end
51
+ end
52
+ end
53
+
54
+ def find_one(id, options)
55
+ http_handler_orm.make_the_call(:get, options, id) do |remote_call|
56
+ remote_call.response = new remote_call.get_attributes(model_name_downcase)
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+ def save(options = {})
63
+ begin
64
+ save!(options)
65
+ rescue Exception => exception
66
+ send("exception=", exception)
67
+ false
68
+ end
69
+ end
70
+
71
+ def save!(options = {})
72
+ options = build_options_for_save(options)
73
+
74
+ if new_record?
75
+ http_handler_orm.make_the_call(:post, options, '') { |remote_call| after_create_update_or_destroy(remote_call) }
76
+ else
77
+ http_handler_orm.make_the_call(:put, options, id) { |remote_call| after_create_update_or_destroy(remote_call) }
78
+ end
79
+ end
80
+
81
+ def destroy(options = {})
82
+ return true if new_record?
83
+
84
+ http_handler_orm.make_the_call(:delete, options, id) do |remote_call|
85
+ after_create_update_or_destroy(remote_call)
86
+ end
87
+ end
88
+
89
+ private ####################### private #######################
90
+
91
+ def build_options_for_save(options = {})
92
+ options ||= {}
93
+ options[self.class.model_name_downcase] ||= safe_table_hash
94
+ options
95
+ end
96
+
97
+ def after_create_update_or_destroy(remote_call)
98
+ new_attributes = remote_call.get_attributes(self.class.model_name_downcase)
99
+ assign_attributes(new_attributes)
100
+ set_raw_response_exception_and_build_proper_response(remote_call)
101
+ end
102
+
103
+ def set_raw_response_exception_and_build_proper_response(remote_call)
104
+ send("last_response=", remote_call.raw_response)
105
+ send("exception=", remote_call.exception)
106
+ remote_call.response = remote_call.successful_response?
107
+ end
108
+
109
+ def last_response=(response)
110
+ @last_response = response
111
+ end
112
+
113
+ def exception=(exception)
114
+ @exception = exception
115
+ end
116
+
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,84 @@
1
+ require "smooth_operator/operator/exceptions"
2
+
3
+ module SmoothOperator
4
+ module Operator
5
+
6
+ class RemoteCall
7
+
8
+ attr_reader :protocol_handler, :raw_response, :parsed_response, :exception
9
+ attr_writer :response
10
+
11
+ HTTP_SUCCESS_CODES = [200, 201, 202, 203, 204]
12
+
13
+ def parse_response # TO BE OVERWRITTEN IF NECESSARY
14
+ @raw_response
15
+ end
16
+
17
+ def successful_response? # TO BE OVERWRITTEN IF NECESSARY
18
+ @raw_response.blank? || HTTP_SUCCESS_CODES.include?(code)
19
+ end
20
+
21
+ def code # TO BE OVERWRITTEN IF NECESSARY
22
+ @raw_response.code
23
+ end
24
+
25
+ def ok?; successful_response?; end
26
+
27
+ def error?; !ok? && exception.present?; end
28
+
29
+ def raw_response=(response)
30
+ @raw_response = response
31
+ @parsed_response = parse_response_and_set_exception_if_necessary
32
+ end
33
+
34
+ def response
35
+ exception.present? ? false : @response
36
+ end
37
+
38
+ def ==(object_to_compare)
39
+ response == object_to_compare
40
+ end
41
+
42
+ def <<(object)
43
+ if response.is_a? Array
44
+ response << object
45
+ else
46
+ response += object
47
+ end
48
+ end
49
+
50
+ def respond_to?(symbol, include_priv = false)
51
+ response.respond_to?(symbol, include_priv)
52
+ end
53
+
54
+ def to_s
55
+ response
56
+ end
57
+
58
+ def get_attributes(key, attributes = nil)
59
+ attributes ||= @parsed_response
60
+
61
+ if attributes.kind_of?(Hash)
62
+ attributes.include?(key) ? attributes[key] : attributes
63
+ else
64
+ attributes
65
+ end
66
+ end
67
+
68
+ protected ####################### protected ##################
69
+
70
+ def parse_response_and_set_exception_if_necessary
71
+ @exception = successful_response? ? nil : SmoothOperator::Operator::Exceptions.raise_proper_exception(@raw_response, code)
72
+ parse_response
73
+ end
74
+
75
+ private ####################### private ######################
76
+
77
+ def method_missing(method, *args, &block)
78
+ response.send(method, *args, &block)
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,16 @@
1
+ module SmoothOperator
2
+
3
+ class Rollback < SmoothOperator::Base
4
+
5
+ def rollback(options = {}, dont_update = false)
6
+ http_handler_orm.make_the_call(:delete, options, "#{version_id}/rollback") do |remote_call|
7
+ set_raw_response_exception_and_build_proper_response(remote_call)
8
+
9
+ new_attributes = remote_call.get_attributes(self.class.model_name_downcase)
10
+ assign_attributes(new_attributes.slice("id", "version_id"))
11
+ end
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -1,3 +1,3 @@
1
1
  module SmoothOperator
2
- VERSION = "0.0.2"
2
+ VERSION = "0.3.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smooth_operator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.3.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-02 00:00:00.000000000 Z
12
+ date: 2013-08-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -73,11 +73,15 @@ files:
73
73
  - Rakefile
74
74
  - lib/smooth_operator.rb
75
75
  - lib/smooth_operator/base.rb
76
- - lib/smooth_operator/exceptions.rb
77
- - lib/smooth_operator/open_struct.rb
78
- - lib/smooth_operator/operator.rb
79
- - lib/smooth_operator/orm.rb
80
- - lib/smooth_operator/protocol_handler.rb
76
+ - lib/smooth_operator/core.rb
77
+ - lib/smooth_operator/http_handlers/typhoeus/base.rb
78
+ - lib/smooth_operator/http_handlers/typhoeus/orm.rb
79
+ - lib/smooth_operator/http_handlers/typhoeus/remote_call.rb
80
+ - lib/smooth_operator/operator/base.rb
81
+ - lib/smooth_operator/operator/exceptions.rb
82
+ - lib/smooth_operator/operator/orm.rb
83
+ - lib/smooth_operator/operator/remote_call.rb
84
+ - lib/smooth_operator/rollback.rb
81
85
  - lib/smooth_operator/version.rb
82
86
  - smooth_operator.gemspec
83
87
  homepage: https://github.com/goncalvesjoao/smooth_operator
@@ -1,60 +0,0 @@
1
- module SmoothOperator
2
- module Exceptions
3
-
4
- extend self
5
-
6
- def raise_proper_exception(response)
7
- return nil if CODES_TO_IGNORE.include?(response.code)
8
- exception_to_raise = (CODE_VS_EXCEPTIONS[response.code] || SmoothOperator::Exceptions::Unknown).new(response)
9
- raise exception_to_raise, exception_to_raise.message
10
- end
11
-
12
- class Base < StandardError
13
- attr_reader :response
14
-
15
- def initialize(response)
16
- @response = response
17
- end
18
- end
19
-
20
- class Unknown < SmoothOperator::Exceptions::Base
21
- def message
22
- 'Unknown Error'
23
- end
24
- end
25
-
26
- class NotFound < SmoothOperator::Exceptions::Base
27
- def message
28
- 'NotFound'
29
- end
30
- end
31
-
32
- class EntityNotProcessed < SmoothOperator::Exceptions::Base
33
- def message
34
- 'EntityNotProcessed'
35
- end
36
- end
37
-
38
- class ServerError < SmoothOperator::Exceptions::Base
39
- def message
40
- 'ServerError'
41
- end
42
- end
43
-
44
- class AuthorizationRequired < SmoothOperator::Exceptions::Base
45
- def message
46
- 'AuthorizationRequired'
47
- end
48
- end
49
-
50
- CODES_TO_IGNORE = [200]
51
-
52
- CODE_VS_EXCEPTIONS = {
53
- 401 => AuthorizationRequired,
54
- 422 => EntityNotProcessed,
55
- 404 => NotFound,
56
- 500 => ServerError
57
- }
58
-
59
- end
60
- end
@@ -1,16 +0,0 @@
1
- module SmoothOperator
2
- module OpenStruct
3
-
4
- extend self # extends the module Class with its instance methods and
5
- # makes it possible do 'SmoothOperator::OpenStruct.new'
6
-
7
- def new(attributes = {})
8
- ::OpenStruct.new(attributes).extend(SmoothOperator::OpenStruct)
9
- end
10
-
11
- def to_hash
12
- @table
13
- end
14
-
15
- end
16
- end
@@ -1,100 +0,0 @@
1
- require "smooth_operator/protocol_handler"
2
-
3
- module SmoothOperator
4
- module Operator
5
-
6
- HTTP_SUCCESS_CODES = [200, 201, 202, 203, 204]
7
-
8
- def self.included(base)
9
- base.extend(ClassMethods)
10
- end
11
-
12
- module ClassMethods
13
-
14
- attr_writer :endpoint
15
- def endpoint
16
- @endpoint ||= ENV["API_ENDPOINT"]
17
- end
18
-
19
- attr_writer :endpoint_user
20
- def endpoint_user
21
- @endpoint_user ||= ENV["API_USER"]
22
- end
23
-
24
- attr_writer :endpoint_pass
25
- def endpoint_pass
26
- @endpoint_pass ||= ENV["API_PASS"]
27
- end
28
-
29
- def get(relative_path, options = {})
30
- make_the_call(:get, relative_path, SmoothOperator::ProtocolHandler.get_options(options))
31
- end
32
-
33
- def post(relative_path, options = {})
34
- make_the_call(:post, relative_path, SmoothOperator::ProtocolHandler.post_options(options))
35
- end
36
-
37
- def put(relative_path, options = {})
38
- make_the_call(:put, relative_path, SmoothOperator::ProtocolHandler.put_options(options))
39
- end
40
-
41
- def delete(relative_path, options = {})
42
- make_the_call(:delete, relative_path, SmoothOperator::ProtocolHandler.delete_options(options))
43
- end
44
-
45
-
46
- def safe_get(relative_path, options = {})
47
- safe_response(get(relative_path, options)) rescue nil
48
- end
49
-
50
- def safe_post(relative_path, options = {})
51
- safe_response(post(relative_path, options)) rescue nil
52
- end
53
-
54
- def safe_put(relative_path, options = {})
55
- safe_response(put(relative_path, options)) rescue nil
56
- end
57
-
58
- def safe_delete(relative_path, options = {})
59
- safe_response(delete(relative_path, options)) rescue nil
60
- end
61
-
62
- def safe_response(response)
63
- successful_response?(response) ? response.parsed_response : nil
64
- end
65
-
66
-
67
- def make_the_call(http_verb, relative_path, options = {})
68
- url = build_url(relative_path)
69
- options = build_options(options)
70
- response = SmoothOperator::ProtocolHandler.send(http_verb, url, options)
71
- response
72
- end
73
-
74
- def build_url(relative_path)
75
- slash = '/' if relative_path.present?
76
- extention = '.json'
77
- [endpoint, table_name, slash, relative_path.to_s, extention].join
78
- end
79
-
80
- def set_basic_auth_credentials(options)
81
- if endpoint_user.present? || endpoint_pass.present? && !options.include?(:basic_auth)
82
- options.merge({ basic_auth: { username: endpoint_user, password: endpoint_pass } })
83
- else
84
- options
85
- end
86
- end
87
-
88
- def build_options(options)
89
- options = {} if options.blank?
90
- set_basic_auth_credentials(options)
91
- end
92
-
93
- def successful_response?(response)
94
- HTTP_SUCCESS_CODES.include?(response.code) || response.blank?
95
- end
96
-
97
- end
98
-
99
- end
100
- end
@@ -1,154 +0,0 @@
1
- require "smooth_operator/exceptions"
2
-
3
- module SmoothOperator
4
- module ORM
5
-
6
- def self.included(base)
7
- base.extend(ClassMethods)
8
- base.send(:attr_reader, :last_response)
9
- end
10
-
11
- module ClassMethods
12
-
13
- attr_writer :save_attr_black_list
14
- def save_attr_black_list
15
- @save_attr_black_list ||= [:id, :created_at, :updated_at]
16
- end
17
-
18
- attr_writer :save_attr_white_list
19
- def save_attr_white_list
20
- @save_attr_white_list ||= []
21
- end
22
-
23
- def find(id, options = {})
24
- if id == :all
25
- find_each(options)
26
- else
27
- find_one(id, options)
28
- end
29
- end
30
-
31
- def safe_find(id, options = {})
32
- begin
33
- find(id, options)
34
- rescue Exception => exception #exception.response contains the server response
35
- id == :all ? [] : nil
36
- end
37
- end
38
-
39
- attr_writer :model_name
40
- def model_name
41
- @model_name ||= name.split('::').last.underscore.capitalize
42
- end
43
-
44
- def model_name_downcase
45
- model_name.downcase
46
- end
47
-
48
- attr_writer :table_name
49
- def table_name
50
- @table_name ||= model_name_downcase.to_s.pluralize
51
- end
52
-
53
- private #------------------------------------------------ private
54
-
55
- def instantiate_each(objects)
56
- objects.map { |object| new(object) }
57
- end
58
-
59
- def find_each(options)
60
- response = get(nil, options)
61
- parsed_response = parse_response_or_raise_proper_exception(response)
62
- parsed_response.kind_of?(Array) ? instantiate_each(parsed_response) : parsed_response
63
- end
64
-
65
- def find_one(id, options)
66
- response = get(id, options)
67
- parsed_response = parse_response_or_raise_proper_exception(response)
68
- new(parsed_response)
69
- end
70
-
71
- def parse_response_or_raise_proper_exception(response)
72
- if successful_response?(response)
73
- response.parsed_response
74
- else
75
- SmoothOperator::Exceptions.raise_proper_exception(response)
76
- end
77
- end
78
-
79
- end
80
-
81
- def save
82
- begin
83
- save!
84
- rescue Exception => exception
85
- false
86
- end
87
- end
88
-
89
- def save!
90
- @last_response = create_or_update
91
- import_response_errors(@last_response)
92
- SmoothOperator::Exceptions.raise_proper_exception(@last_response) unless self.class.successful_response?(@last_response)
93
- true
94
- end
95
-
96
- def destroy
97
- return true if new_record?
98
-
99
- @last_response = self.class.delete(self.id)
100
- import_response_errors(@last_response)
101
- self.class.successful_response?(@last_response)
102
- end
103
-
104
- def new_record?
105
- !persisted?
106
- end
107
-
108
- def persisted?
109
- try(:id).present?
110
- end
111
-
112
- def to_partial_path
113
- class_name_plural = self.class.table_name
114
- "#{class_name_plural}/#{class_name_plural.singularize}"
115
- end
116
-
117
- def valid?
118
- errors.blank?
119
- end
120
-
121
- def invalid?
122
- !valid?
123
- end
124
-
125
- def hash_of_safe_content
126
- safe_hash = hash_of_full_content.dup
127
-
128
- if self.class.save_attr_white_list.present?
129
- safe_hash.slice!(*self.class.save_attr_white_list)
130
- else
131
- self.class.save_attr_black_list.each { |attribute| safe_hash.delete(attribute) }
132
- end
133
-
134
- safe_hash
135
- end
136
-
137
- private #-------------------------------------- private
138
-
139
- def create_or_update
140
- if new_record?
141
- self.class.post('', { self.class.model_name_downcase => hash_of_safe_content })
142
- else
143
- self.class.put(self.id, { self.class.model_name_downcase => hash_of_safe_content })
144
- end
145
- end
146
-
147
- def import_response_errors(response)
148
- if response.present? && response.parsed_response.include?('errors')
149
- self.errors = response.parsed_response['errors']
150
- end
151
- end
152
-
153
- end
154
- end
@@ -1,26 +0,0 @@
1
- require 'httparty'
2
-
3
- module SmoothOperator
4
- class ProtocolHandler
5
-
6
- include ::HTTParty
7
- format :json
8
-
9
- def self.get_options(options)
10
- { query: options }
11
- end
12
-
13
- def self.post_options(options)
14
- { body: options }
15
- end
16
-
17
- def self.put_options(options)
18
- { body: options }
19
- end
20
-
21
- def self.delete_options(options)
22
- { body: options }
23
- end
24
-
25
- end
26
- end