active_jobject 0.1.1 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 25a4e56c18e49c5151fef9020b24fa6ff7e9c5f753e7bc31035cfd906fb27c41
4
- data.tar.gz: f39f850277672136d0d87ef6685088f480c09218a7a27879e4d79ad1665016b6
3
+ metadata.gz: 670bb39c934b36b744850d38292acbd8a4f52f803ce5a1e1fbb63ded05f7214f
4
+ data.tar.gz: '077906e8eb34e510ace5ccd53987cbe7c93d30bcca4a0e3a0d288a33bba10354'
5
5
  SHA512:
6
- metadata.gz: c64b52c489aeb0e289fa348ae08583a5ba8f523a2cfec7222f1bbf265ca28e557d76f0fe6bd0a24e711c64321f6c0366503b87c185358caf31ea58f3ac94aab4
7
- data.tar.gz: a906370c3219908a1b1ca5dbd9c3b5270b05a9b9326eaf72398bfdc4b856135332202546ccb38877a3b393e0e8254ed5bfb86f5f9e6ecd71e3fff16e4d3e5f33
6
+ metadata.gz: fc1677943c1e48da4948b863efb15bdc98a9704e4a7b9ad26ad1c19e497ee01606705d28f222359bee21dfc950d6661807a2fc9cc5ace8906137e41501ca7ad2
7
+ data.tar.gz: 935bc42d0d4623293abaa99821955689e03c2e5cf28888cc57d4ffed400452d72cc8f79e3915ae392be2e4162bc579f53ef253406df4f3182efc86e5edb6042d
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # ActiveJobject
2
+ [![Gem Version](https://badge.fury.io/rb/active_jobject.svg?icon=si%3Arubygems)](https://badge.fury.io/rb/active_jobject)
2
3
 
3
4
  Yes ActiveJobject, as in Active JSON Object (clever I know). This gem is built as a wraper for handling external connections with parsers and authentication built-in. It also supports
4
5
  several HTTP request / gem so you can use your own `engine` or gem that better suits your needs. It also comes packaged with it's own error handling, allowing for more consistent and standard error handling cross-project.
@@ -4,20 +4,62 @@ module ActiveJobject
4
4
  class Base
5
5
  include ActiveJobject::Request
6
6
 
7
+ def initialize(**)
8
+ parse(self, **)
9
+ end
10
+
7
11
  class << self
8
- attr_accessor :_site
12
+ attr_writer :_site, :_ignored_keys
9
13
 
10
- def site
11
- _site
14
+ def _site
15
+ if defined?(@_site)
16
+ @_site
17
+ elsif superclass.respond_to?(:_site)
18
+ superclass._site
19
+ end
12
20
  end
13
21
 
14
- def site=(site)
15
- self._site = site
22
+ alias site _site
23
+ alias site= _site=
24
+
25
+ def _ignored_keys
26
+ if instance_variable_defined?(:@_ignored_keys)
27
+ @_ignored_keys
28
+ elsif superclass.respond_to?(:_ignored_keys)
29
+ superclass._ignored_keys
30
+ else
31
+ []
32
+ end
33
+ end
34
+
35
+ alias ignored_keys _ignored_keys
36
+ alias ignored_keys= _ignored_keys=
37
+
38
+ def uri
39
+ _site.is_a?(URI) ? _site : URI(_site)
16
40
  end
17
41
  end
18
42
 
19
- def uri
20
- self.class._site.is_a?(URI) ? self.class._site : URI(self.class._site)
43
+ def uri = self.class.uri
44
+
45
+ def to_h(symbolize_keys: true)
46
+ instance_variables.to_h do |var|
47
+ key = var.to_s.delete('@')
48
+ key = key.to_sym if symbolize_keys
49
+
50
+ [key, serialize_value(instance_variable_get(var), symbolize_keys:)]
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def serialize_value(value, symbolize_keys:)
57
+ case value
58
+ when ActiveJobject::Base then value.to_h(symbolize_keys:)
59
+ when Array then value.map { |v| serialize_value(v, symbolize_keys:) }
60
+ when Hash then value.transform_values { |v| serialize_value(v, symbolize_keys:) }
61
+ else value
62
+ end
21
63
  end
22
64
  end
23
65
  end
@@ -8,15 +8,10 @@ module ActiveJobject
8
8
  raise InvalidInstance, "Class #{klass&.name || klass} is not an instance." if klass.is_a?(Class)
9
9
 
10
10
  attributes.each do |attribute, value|
11
- return_value = if value.is_a?(Array)
12
- parse_array(klass, attribute, value)
13
- elsif value.is_a?(Hash)
14
- parse_hash(klass, attribute, value)
15
- else
16
- value
17
- end
11
+ result = parse_method(klass, attribute, value)
12
+ class_method_value = result.nil? ? value : result
18
13
 
19
- define_singleton_methods(klass, attribute, return_value)
14
+ define_singleton_methods(klass, attribute, class_method_value)
20
15
  end
21
16
 
22
17
  klass
@@ -65,5 +60,22 @@ module ActiveJobject
65
60
  base_klass.const_set(name, klass)
66
61
  end
67
62
  end
63
+
64
+ def parse_method(klass, attribute, value)
65
+ return nil if ignored_keys.include?(attribute)
66
+
67
+ case value
68
+ when Array
69
+ return parse_array(klass, attribute, value)
70
+ when Hash
71
+ return parse_hash(klass, attribute, value)
72
+ end
73
+
74
+ nil
75
+ end
76
+
77
+ def ignored_keys
78
+ self.class.ignored_keys || []
79
+ end
68
80
  end
69
81
  end
@@ -96,8 +96,9 @@ module ActiveJobject
96
96
  end
97
97
 
98
98
  def deconstruct_uri(uri)
99
- host_with_scheme = [80, 443].include?(uri.port) ? "#{uri.scheme}://#{uri.host}/" : "#{uri.scheme}://#{uri.host}:#{uri.port}/"
100
- path = uri.path
99
+ default_port = (uri.scheme == 'https' && uri.port == 443) || (uri.scheme == 'http' && uri.port == 80)
100
+ host_with_scheme = default_port ? "#{uri.scheme}://#{uri.host}/" : "#{uri.scheme}://#{uri.host}:#{uri.port}/"
101
+ path = uri.query.nil? ? uri.path : "#{uri.path}?#{uri.query}"
101
102
 
102
103
  [host_with_scheme, path]
103
104
  end
@@ -4,17 +4,27 @@ module ActiveJobject
4
4
  module Request
5
5
  include ActiveJobject::Parser
6
6
 
7
+ class UnsupportedFormat < ActiveJobject::Error; end
8
+
7
9
  def self.included(base)
8
10
  base.extend(ClassMethods)
9
11
  end
10
12
 
11
13
  module ClassMethods
14
+ include ActiveJobject::Parser
15
+
12
16
  def engine=(engine)
13
17
  @engine = engine
14
18
  end
15
19
 
16
20
  def engine
17
- @engine ||= ActiveJobject::Request::Engine::NetHttp
21
+ if instance_variable_defined?(:@engine)
22
+ @engine
23
+ elsif superclass.respond_to?(:engine)
24
+ superclass.engine
25
+ else
26
+ ActiveJobject::Request::Engine::NetHttp
27
+ end
18
28
  end
19
29
 
20
30
  def default_headers=(headers)
@@ -22,30 +32,75 @@ module ActiveJobject
22
32
  end
23
33
 
24
34
  def default_headers
25
- @default_headers ||= {}
35
+ if instance_variable_defined?(:@default_headers)
36
+ @default_headers
37
+ elsif superclass.respond_to?(:default_headers)
38
+ superclass.default_headers
39
+ else
40
+ {}
41
+ end
26
42
  end
27
- end
28
43
 
29
- def get(headers: {}, params: {})
30
- merged_headers = self.class.default_headers.merge(headers)
31
- response = self.class.engine.get(site: uri, headers: merged_headers, params:)
44
+ private
32
45
 
33
- parse(self, **JSON.parse(response.body))
34
- end
46
+ def get(endpoint:, headers: {}, params: {})
47
+ merged_headers = default_headers.merge(headers)
48
+ response = engine.get(site: uri + endpoint, headers: merged_headers, params:)
35
49
 
36
- def post(headers: {}, params: {}, body: nil)
37
- merged_headers = self.class.default_headers.merge(headers)
38
- response = self.class.engine.post(site: uri, headers: merged_headers, params:, body:)
50
+ build_response(JSON.parse(response.body))
51
+ end
39
52
 
40
- parse(self, **JSON.parse(response.body))
41
- end
53
+ def post(endpoint:, headers: {}, params: {}, body: nil)
54
+ merged_headers = default_headers.merge(headers)
55
+ response = engine.post(site: uri + endpoint, headers: merged_headers, params:, body:)
42
56
 
43
- def put; end
57
+ build_response(JSON.parse(response.body))
58
+ end
59
+
60
+ def put(endpoint:, headers: {}, params: {}, body: nil)
61
+ merged_headers = default_headers.merge(headers)
62
+ response = engine.put(site: uri + endpoint, headers: merged_headers, params:, body:)
63
+
64
+ build_response(JSON.parse(response.body))
65
+ end
66
+
67
+ def patch(endpoint:, headers: {}, params: {}, body: nil)
68
+ merged_headers = default_headers.merge(headers)
69
+ response = engine.patch(site: uri + endpoint, headers: merged_headers, params:, body:)
44
70
 
45
- def delete; end
71
+ build_response(JSON.parse(response.body))
72
+ end
73
+
74
+ def delete(endpoint:, headers: {}, params: {})
75
+ merged_headers = default_headers.merge(headers)
76
+ response = engine.delete(site: uri + endpoint, headers: merged_headers, params:)
77
+
78
+ build_response(JSON.parse(response.body))
79
+ end
80
+
81
+ def build_response(json)
82
+ if json.is_a?(Hash)
83
+ parse(new, **json)
84
+ elsif json.is_a?(Array)
85
+ ActiveJobject::Collection.new(json.map { |res| parse(new, **res) })
86
+ else
87
+ raise UnsupportedFormat "HTTP response not supported. (#{json.class})"
88
+ end
89
+ end
90
+ end
46
91
 
47
92
  private
48
93
 
94
+ def get(endpoint:, headers: {}, params: {}) = self.class.get(endpoint:, headers:, params:)
95
+
96
+ def post(endpoint:, headers: {}, params: {}, body: nil) = self.class.post(endpoint:, headers:, params:, body:)
97
+
98
+ def put(endpoint:, headers: {}, params: {}, body: nil) = self.class.put(endpoint:, headers:, params:, body:)
99
+
100
+ def patch(endpoint:, headers: {}, params: {}, body: nil) = self.class.patch(endpoint:, headers:, params:, body:)
101
+
102
+ def delete(endpoint:, headers: {}, params: {}, body: nil) = self.class.delete(endpoint:, headers:, params:, body:)
103
+
49
104
  def error_class(status)
50
105
  case status
51
106
  when 404
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveJobject
4
- VERSION = '0.1.1'
4
+ VERSION = '0.2.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_jobject
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guilherme Theodoro
@@ -54,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
54
54
  - !ruby/object:Gem::Version
55
55
  version: '0'
56
56
  requirements: []
57
- rubygems_version: 3.6.9
57
+ rubygems_version: 4.0.20
58
58
  specification_version: 4
59
59
  summary: HTTP Engine Object Wrapper
60
60
  test_files: []