smooth_operator 1.3.0 → 1.8.0
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 +8 -8
- data/Gemfile +0 -5
- data/README.md +11 -308
- data/console.rb +3 -28
- data/lib/smooth_operator.rb +7 -75
- data/lib/smooth_operator/array_with_meta_data.rb +21 -20
- data/lib/smooth_operator/attribute_assignment.rb +53 -57
- data/lib/smooth_operator/delegation.rb +34 -15
- data/lib/smooth_operator/finder_methods.rb +17 -33
- data/lib/smooth_operator/helpers.rb +7 -37
- data/lib/smooth_operator/internal_attribute.rb +49 -0
- data/lib/smooth_operator/model_schema.rb +72 -0
- data/lib/smooth_operator/open_struct.rb +4 -7
- data/lib/smooth_operator/operator.rb +64 -102
- data/lib/smooth_operator/persistence.rb +64 -94
- data/lib/smooth_operator/remote_call.rb +70 -0
- data/lib/smooth_operator/serialization.rb +33 -89
- data/lib/smooth_operator/translation.rb +13 -26
- data/lib/smooth_operator/type_converter.rb +69 -0
- data/lib/smooth_operator/validations.rb +3 -25
- data/lib/smooth_operator/version.rb +1 -1
- data/smooth_operator.gemspec +5 -9
- data/spec/factories/user_factory.rb +4 -5
- data/spec/smooth_operator/attribute_assignment_spec.rb +11 -145
- data/spec/smooth_operator/delegation_spec.rb +54 -57
- data/spec/smooth_operator/finder_methods_spec.rb +2 -91
- data/spec/smooth_operator/{resource_name_spec.rb → model_schema_spec.rb} +2 -2
- data/spec/smooth_operator/operator_spec.rb +1 -1
- data/spec/smooth_operator/persistence_spec.rb +20 -140
- data/spec/smooth_operator/serialization_spec.rb +4 -28
- data/spec/spec_helper.rb +9 -7
- data/spec/support/models/address.rb +0 -9
- data/spec/support/models/post.rb +3 -9
- data/spec/support/models/user.rb +7 -30
- data/spec/support/models/user_with_address_and_posts.rb +12 -20
- data/spec/support/test_server.rb +7 -63
- metadata +18 -55
- data/lib/smooth_operator/associations.rb +0 -110
- data/lib/smooth_operator/associations/association_reflection.rb +0 -79
- data/lib/smooth_operator/associations/has_many_relation.rb +0 -45
- data/lib/smooth_operator/associations/reflection.rb +0 -41
- data/lib/smooth_operator/cookie_jar.rb +0 -21
- data/lib/smooth_operator/http_methods.rb +0 -17
- data/lib/smooth_operator/internal_data.rb +0 -45
- data/lib/smooth_operator/operators/connection_wrapper.rb +0 -15
- data/lib/smooth_operator/operators/faraday.rb +0 -75
- data/lib/smooth_operator/operators/typhoeus.rb +0 -87
- data/lib/smooth_operator/options.rb +0 -30
- data/lib/smooth_operator/remote_call/base.rb +0 -76
- data/lib/smooth_operator/remote_call/errors/connection_failed.rb +0 -20
- data/lib/smooth_operator/remote_call/errors/timeout.rb +0 -20
- data/lib/smooth_operator/remote_call/faraday.rb +0 -19
- data/lib/smooth_operator/remote_call/typhoeus.rb +0 -19
- data/lib/smooth_operator/resource_name.rb +0 -46
- data/lib/smooth_operator/schema.rb +0 -21
- data/lib/smooth_operator/type_casting.rb +0 -127
- data/spec/require_helper.rb +0 -11
- data/spec/smooth_operator/remote_call_spec.rb +0 -340
- data/spec/smooth_operator/validations_spec.rb +0 -42
- data/spec/support/models/comment.rb +0 -5
@@ -1,79 +0,0 @@
|
|
1
|
-
require "smooth_operator/associations/reflection"
|
2
|
-
|
3
|
-
module SmoothOperator
|
4
|
-
module Associations
|
5
|
-
class AssociationReflection < Reflection
|
6
|
-
|
7
|
-
attr_reader :related_reflection, :macro
|
8
|
-
|
9
|
-
def initialize(association, related_reflection, options)
|
10
|
-
super(association, options)
|
11
|
-
|
12
|
-
@related_reflection, @macro = related_reflection, options[:macro]
|
13
|
-
end
|
14
|
-
|
15
|
-
def primary_key
|
16
|
-
@primary_key ||= options[:primary_key] || :id
|
17
|
-
end
|
18
|
-
|
19
|
-
def foreign_key
|
20
|
-
@foreign_key ||= options[:foreign_key] || foreign_key_default
|
21
|
-
end
|
22
|
-
|
23
|
-
def set_relational_keys(origin, destination)
|
24
|
-
return nil if options[:standalone] == true
|
25
|
-
|
26
|
-
if has_many? || has_one?
|
27
|
-
set_foreign_key(destination, primary_key_of(origin))
|
28
|
-
elsif belongs_to?
|
29
|
-
set_foreign_key(origin, primary_key_of(destination))
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def set_foreign_key(object, id)
|
34
|
-
setter = "#{foreign_key}="
|
35
|
-
|
36
|
-
if object.respond_to?(setter)
|
37
|
-
object.send(setter, id)
|
38
|
-
elsif object.respond_to?("send_to_representative")
|
39
|
-
object.send_to_representative(setter, id)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def primary_key_of(object)
|
44
|
-
object.send(primary_key)
|
45
|
-
end
|
46
|
-
|
47
|
-
def has_many?
|
48
|
-
macro == :has_many
|
49
|
-
end
|
50
|
-
|
51
|
-
def has_one?
|
52
|
-
macro == :has_one
|
53
|
-
end
|
54
|
-
|
55
|
-
def belongs_to?
|
56
|
-
macro == :belongs_to
|
57
|
-
end
|
58
|
-
|
59
|
-
def collection?
|
60
|
-
has_many?
|
61
|
-
end
|
62
|
-
|
63
|
-
def rails_serialization?
|
64
|
-
options[:rails_serialization] == true
|
65
|
-
end
|
66
|
-
|
67
|
-
private ################################# private
|
68
|
-
|
69
|
-
def foreign_key_default
|
70
|
-
if has_many? || has_one?
|
71
|
-
"#{related_reflection.single_name}_id"
|
72
|
-
elsif belongs_to?
|
73
|
-
"#{single_name}_id"
|
74
|
-
end.to_sym
|
75
|
-
end
|
76
|
-
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
module SmoothOperator
|
2
|
-
module Associations
|
3
|
-
class HasManyRelation < SimpleDelegator
|
4
|
-
|
5
|
-
attr_reader :object, :association
|
6
|
-
|
7
|
-
def initialize(object, association)
|
8
|
-
@object, @association = object, association
|
9
|
-
end
|
10
|
-
|
11
|
-
def reload
|
12
|
-
"TODO"
|
13
|
-
end
|
14
|
-
|
15
|
-
def new(attributes = {})
|
16
|
-
object.class.reflect_on_association(association).klass.new(attributes)
|
17
|
-
end
|
18
|
-
|
19
|
-
def build(attributes = {})
|
20
|
-
new_array, new_array_entry = get_array, new(attributes)
|
21
|
-
|
22
|
-
new_array.push new_array_entry
|
23
|
-
|
24
|
-
object.send("#{association}=", new_array)
|
25
|
-
|
26
|
-
new_array_entry
|
27
|
-
end
|
28
|
-
|
29
|
-
undef :is_a?
|
30
|
-
|
31
|
-
protected ############### PROTECTED ###############
|
32
|
-
|
33
|
-
def get_array
|
34
|
-
data = object.internal_data_get(association.to_s)
|
35
|
-
|
36
|
-
data.nil? ? [] : [*data]
|
37
|
-
end
|
38
|
-
|
39
|
-
def refresh
|
40
|
-
__setobj__ get_array
|
41
|
-
end
|
42
|
-
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
module SmoothOperator
|
2
|
-
module Associations
|
3
|
-
class Reflection
|
4
|
-
|
5
|
-
attr_reader :name, :klass, :options
|
6
|
-
|
7
|
-
def initialize(class_name, options)
|
8
|
-
options = options.is_a?(Hash) ? options : {}
|
9
|
-
|
10
|
-
@name, @options = class_name, options
|
11
|
-
|
12
|
-
@klass = options[:class_name] || klass_default(@name)
|
13
|
-
|
14
|
-
if options.include?(:class_name) && options[:class_name].nil?
|
15
|
-
@klass = nil
|
16
|
-
elsif @klass.is_a?(String)
|
17
|
-
@klass = @klass.constantize rescue OpenStruct
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def single_name
|
22
|
-
@single_name ||= options[:single_name] || name.to_s.singularize
|
23
|
-
end
|
24
|
-
|
25
|
-
def plural_name
|
26
|
-
@plural_name ||= options[:plural_name] || name.to_s.pluralize
|
27
|
-
end
|
28
|
-
|
29
|
-
private ################################# private
|
30
|
-
|
31
|
-
def klass_default(class_name)
|
32
|
-
if Helpers.plural?(class_name)
|
33
|
-
class_name.to_s.singularize.camelize
|
34
|
-
else
|
35
|
-
class_name.to_s.camelize
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
module SmoothOperator
|
2
|
-
class CookieJar < Hash
|
3
|
-
|
4
|
-
def to_s
|
5
|
-
self.map { |key, value| "#{key}=#{value}"}.join("; ")
|
6
|
-
end
|
7
|
-
|
8
|
-
def parse(*cookie_strings)
|
9
|
-
cookie_strings.each do |cookie_string|
|
10
|
-
next unless cookie_string.is_a?(String)
|
11
|
-
|
12
|
-
key, value = cookie_string.split('; ').first.split('=', 2)
|
13
|
-
|
14
|
-
self[key] = value
|
15
|
-
end
|
16
|
-
|
17
|
-
self
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module SmoothOperator
|
2
|
-
module HttpMethods
|
3
|
-
|
4
|
-
HTTP_VERBS = %w[get post put patch delete]
|
5
|
-
|
6
|
-
HTTP_VERBS.each do |method|
|
7
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
8
|
-
def #{method}(relative_path = '', params = {}, options = {})
|
9
|
-
make_the_call(:#{method}, relative_path, params, options) do |remote_call|
|
10
|
-
block_given? ? yield(remote_call) : remote_call
|
11
|
-
end
|
12
|
-
end
|
13
|
-
RUBY
|
14
|
-
end
|
15
|
-
|
16
|
-
end
|
17
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'smooth_operator/type_casting'
|
2
|
-
|
3
|
-
module SmoothOperator
|
4
|
-
module InternalData
|
5
|
-
|
6
|
-
def internal_data
|
7
|
-
@internal_data ||= {}
|
8
|
-
end
|
9
|
-
|
10
|
-
def known_attributes
|
11
|
-
return @known_attributes if defined?(@known_attributes)
|
12
|
-
|
13
|
-
schema_attributes = if self.class.respond_to?(:internal_structure)
|
14
|
-
self.class.internal_structure.keys
|
15
|
-
else
|
16
|
-
[]
|
17
|
-
end
|
18
|
-
|
19
|
-
@known_attributes = Set.new(schema_attributes)
|
20
|
-
end
|
21
|
-
|
22
|
-
def known_attribute?(attribute)
|
23
|
-
known_attributes.include?(attribute.to_s)
|
24
|
-
end
|
25
|
-
|
26
|
-
def internal_data_get(attribute_name)
|
27
|
-
internal_data[attribute_name]
|
28
|
-
end
|
29
|
-
|
30
|
-
def internal_data_push(attribute_name, attribute_value)
|
31
|
-
attribute_name = attribute_name.to_s
|
32
|
-
|
33
|
-
known_attributes.add attribute_name
|
34
|
-
|
35
|
-
internal_data[attribute_name] = TypeCasting.cast_to_type(attribute_name, attribute_value, self)
|
36
|
-
|
37
|
-
if self.class.respond_to?(:smooth_operator?)
|
38
|
-
marked_for_destruction?(attribute_value) if attribute_name == self.class.destroy_key
|
39
|
-
|
40
|
-
new_record?(true) if attribute_name == self.class.primary_key
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
45
|
-
end
|
@@ -1,75 +0,0 @@
|
|
1
|
-
require 'faraday'
|
2
|
-
require 'typhoeus/adapters/faraday'
|
3
|
-
require "smooth_operator/remote_call/faraday"
|
4
|
-
|
5
|
-
module SmoothOperator
|
6
|
-
|
7
|
-
module Operators
|
8
|
-
|
9
|
-
module Faraday
|
10
|
-
|
11
|
-
extend self
|
12
|
-
|
13
|
-
# def generate_parallel_connection
|
14
|
-
# generate_connection(:typhoeus)
|
15
|
-
# end
|
16
|
-
|
17
|
-
def generate_connection(adapter = nil, options = nil)
|
18
|
-
adapter ||= :net_http
|
19
|
-
|
20
|
-
ConnectionWrapper.new(::Faraday.new(url: options[:endpoint]) do |builder|
|
21
|
-
builder.options[:timeout] = options[:timeout].to_i unless Helpers.blank?(options[:timeout])
|
22
|
-
builder.request :url_encoded
|
23
|
-
builder.adapter adapter
|
24
|
-
end)
|
25
|
-
end
|
26
|
-
|
27
|
-
def make_the_call(http_verb, resource_path, params, body, options)
|
28
|
-
connection, request_options, options = strip_options(options)
|
29
|
-
|
30
|
-
remote_call = begin
|
31
|
-
set_basic_authentication(connection, options)
|
32
|
-
|
33
|
-
response = connection.send(http_verb, resource_path) do |request|
|
34
|
-
request_configuration(request, request_options, options, params, body)
|
35
|
-
end
|
36
|
-
|
37
|
-
RemoteCall::Faraday.new(response)
|
38
|
-
rescue ::Faraday::Error::ConnectionFailed
|
39
|
-
RemoteCall::Errors::ConnectionFailed.new(response)
|
40
|
-
rescue ::Faraday::Error::TimeoutError
|
41
|
-
RemoteCall::Errors::Timeout.new(response)
|
42
|
-
end
|
43
|
-
|
44
|
-
block_given? ? yield(remote_call) : remote_call
|
45
|
-
end
|
46
|
-
|
47
|
-
|
48
|
-
protected ################ PROTECTED ################
|
49
|
-
|
50
|
-
def strip_options(options)
|
51
|
-
request_options = options.delete(:request_options) || {}
|
52
|
-
|
53
|
-
connection = (options.delete(:connection) || generate_connection(nil, options)).connection
|
54
|
-
|
55
|
-
[connection, request_options, options]
|
56
|
-
end
|
57
|
-
|
58
|
-
def set_basic_authentication(connection, options)
|
59
|
-
connection.basic_auth(options[:endpoint_user], options[:endpoint_pass]) if Helpers.present?(options[:endpoint_user])
|
60
|
-
end
|
61
|
-
|
62
|
-
def request_configuration(request, request_options, options, params, body)
|
63
|
-
request_options.each { |key, value| request.options.send("#{key}=", value) }
|
64
|
-
|
65
|
-
options[:headers].each { |key, value| request.headers[key] = value }
|
66
|
-
|
67
|
-
params.each { |key, value| request.params[key] = value }
|
68
|
-
|
69
|
-
request.body = body
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
75
|
-
end
|
@@ -1,87 +0,0 @@
|
|
1
|
-
require 'typhoeus'
|
2
|
-
require "smooth_operator/remote_call/typhoeus"
|
3
|
-
|
4
|
-
module SmoothOperator
|
5
|
-
|
6
|
-
module Operators
|
7
|
-
|
8
|
-
module Typhoeus
|
9
|
-
|
10
|
-
extend self
|
11
|
-
|
12
|
-
def generate_parallel_connection
|
13
|
-
generate_connection
|
14
|
-
end
|
15
|
-
|
16
|
-
def generate_connection(adapter = nil, options = nil)
|
17
|
-
ConnectionWrapper.new(::Typhoeus::Hydra::hydra)
|
18
|
-
end
|
19
|
-
|
20
|
-
def make_the_call(http_verb, resource_path, params, body, options)
|
21
|
-
request = ::Typhoeus::Request.new *typhoeus_request_args(http_verb, resource_path, params, body, options)
|
22
|
-
|
23
|
-
hydra = (options[:connection] || generate_connection).connection
|
24
|
-
|
25
|
-
request_result = nil
|
26
|
-
|
27
|
-
hydra.queue(request)
|
28
|
-
|
29
|
-
request.on_complete do |typhoeus_response|
|
30
|
-
remote_call = remote_call(typhoeus_response)
|
31
|
-
|
32
|
-
if block_given?
|
33
|
-
request_result = yield(remote_call)
|
34
|
-
else
|
35
|
-
request_result = remote_call
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
hydra.run if Helpers.blank?(options[:connection])
|
40
|
-
|
41
|
-
request_result
|
42
|
-
end
|
43
|
-
|
44
|
-
protected ################ PROTECTED ################
|
45
|
-
|
46
|
-
def typhoeus_request_args(http_verb, relative_path, params, body, options)
|
47
|
-
[url(options, relative_path), build_typhoeus_options(http_verb, params, body, options)]
|
48
|
-
end
|
49
|
-
|
50
|
-
def remote_call(typhoeus_response)
|
51
|
-
if typhoeus_response.return_code == :couldnt_connect
|
52
|
-
RemoteCall::Errors::ConnectionFailed
|
53
|
-
elsif typhoeus_response.timed_out?
|
54
|
-
RemoteCall::Errors::Timeout
|
55
|
-
else
|
56
|
-
RemoteCall::Typhoeus
|
57
|
-
end.new(typhoeus_response)
|
58
|
-
end
|
59
|
-
|
60
|
-
private ################### PRIVATE ###############
|
61
|
-
|
62
|
-
def build_typhoeus_options(http_verb, params, body, options)
|
63
|
-
typhoeus_options = { method: http_verb, headers: options[:headers].merge({ "Content-type" => "application/x-www-form-urlencoded" }) }
|
64
|
-
|
65
|
-
typhoeus_options[:timeout] = options[:timeout] if Helpers.present?(options[:timeout])
|
66
|
-
|
67
|
-
typhoeus_options[:body] = body if Helpers.present?(body)
|
68
|
-
|
69
|
-
typhoeus_options[:params] = params if Helpers.present?(params)
|
70
|
-
|
71
|
-
typhoeus_options[:userpwd] = "#{options[:endpoint_user]}:#{options[:endpoint_pass]}" if Helpers.present?(options[:endpoint_user])
|
72
|
-
|
73
|
-
typhoeus_options
|
74
|
-
end
|
75
|
-
|
76
|
-
def url(options, relative_path)
|
77
|
-
url = options[:endpoint]
|
78
|
-
|
79
|
-
slice = url[-1] != '/' ? '/' : ''
|
80
|
-
|
81
|
-
url = "#{url}#{slice}#{relative_path}" if Helpers.present?(relative_path)
|
82
|
-
end
|
83
|
-
|
84
|
-
end
|
85
|
-
|
86
|
-
end
|
87
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module SmoothOperator
|
2
|
-
module Options
|
3
|
-
|
4
|
-
def get_option(option, default, *args)
|
5
|
-
return default unless config_options.include?(option)
|
6
|
-
|
7
|
-
_option = config_options[option]
|
8
|
-
|
9
|
-
case _option
|
10
|
-
when Symbol
|
11
|
-
respond_to?(_option) ? send(_option, *args) : _option
|
12
|
-
when Proc
|
13
|
-
_option.call(*args)
|
14
|
-
else
|
15
|
-
_option
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def config_options
|
20
|
-
Helpers.get_instance_variable(self, :config_options, {})
|
21
|
-
end
|
22
|
-
|
23
|
-
def smooth_operator_options(options = {})
|
24
|
-
config_options.merge!(options)
|
25
|
-
end
|
26
|
-
|
27
|
-
alias_method :options, :smooth_operator_options
|
28
|
-
|
29
|
-
end
|
30
|
-
end
|