resteze 0.1.0 → 0.3.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 +4 -4
- data/.rubocop.yml +11 -1
- data/.ruby-version +1 -0
- data/CHANGELOG.md +31 -0
- data/Guardfile +0 -1
- data/README.md +61 -13
- data/assets/resteze.png +0 -0
- data/assets/resteze.svg +3 -0
- data/lib/resteze/api_module.rb +25 -0
- data/lib/resteze/api_resource.rb +70 -0
- data/lib/resteze/client.rb +242 -0
- data/lib/resteze/errors.rb +38 -0
- data/lib/resteze/list.rb +43 -0
- data/lib/resteze/list_object.rb +40 -0
- data/lib/resteze/middleware/raise_error.rb +17 -0
- data/lib/resteze/object.rb +73 -0
- data/lib/resteze/request.rb +14 -0
- data/lib/resteze/response.rb +52 -0
- data/lib/resteze/save.rb +35 -0
- data/lib/resteze/testing/minitest/configuration.rb +18 -0
- data/lib/resteze/testing/minitest/object.rb +58 -0
- data/lib/resteze/testing/minitest.rb +10 -0
- data/lib/resteze/testing/rspec/configure.rb +16 -0
- data/lib/resteze/testing/rspec/object.rb +49 -0
- data/lib/resteze/testing/rspec.rb +10 -0
- data/lib/resteze/util.rb +54 -0
- data/lib/resteze/version.rb +1 -1
- data/lib/resteze.rb +122 -3
- metadata +27 -5
@@ -0,0 +1,58 @@
|
|
1
|
+
module Resteze
|
2
|
+
module Testing
|
3
|
+
module Minitest
|
4
|
+
module Object
|
5
|
+
include ActiveSupport::Concern
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
# rubocop:disable Metrics/AbcSize
|
10
|
+
# rubocop:disable Naming/PredicatePrefix
|
11
|
+
def has_property(name, **options)
|
12
|
+
assert subject.property?(name.to_sym), "Expected #{subject} to have property: #{name}"
|
13
|
+
assert_property_default(name, options[:default]) if options.key?(:default)
|
14
|
+
assert_property_translation(name, options[:from]) if options.key?(:from)
|
15
|
+
assert_property_transformed(name, transformed: options[:transformed]) if options.key?(:transformed)
|
16
|
+
assert_property_required(name, required: options[:required]) if options.key?(:required)
|
17
|
+
end
|
18
|
+
# rubocop:enable Metrics/AbcSize
|
19
|
+
# rubocop:enable Naming/PredicatePrefix
|
20
|
+
|
21
|
+
def assert_property_transformed(name, transformed: true)
|
22
|
+
translation = subject.translations_hash.dig(subject.translations.key(name.to_sym), name.to_sym)
|
23
|
+
transformation_defined = translation.is_a?(Proc) || subject.transformation_exists?(name.to_sym)
|
24
|
+
|
25
|
+
if transformed
|
26
|
+
assert transformation_defined, "Expected #{subject} to transform property: #{name}"
|
27
|
+
else
|
28
|
+
refute transformation_defined, "Expected #{subject} not to transform property: #{name}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def assert_property_required(name, required: true)
|
33
|
+
if required
|
34
|
+
assert subject.required?(name.to_sym), "Expected #{subject} to require property: #{name}"
|
35
|
+
else
|
36
|
+
refute subject.required?(name.to_sym), "Expected #{subject} not to require property: #{name}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def assert_property_translation(name, from)
|
41
|
+
assert_equal(
|
42
|
+
from.to_sym,
|
43
|
+
subject.translations.key(name.to_sym),
|
44
|
+
"Expected #{subject} to map property #{name} from #{from}"
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
def assert_property_default(name, default)
|
49
|
+
assert_equal(
|
50
|
+
default,
|
51
|
+
subject.defaults[name.to_sym],
|
52
|
+
"Expected #{subject} to have default for property #{name}"
|
53
|
+
)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Resteze
|
2
|
+
module Testing
|
3
|
+
module Configuration
|
4
|
+
# Assert that a config property is supported and can be assigned
|
5
|
+
def assert_config_property(property, value = nil, subject: nil)
|
6
|
+
subject ||= (defined?(@subject) && @subject) || self.subject
|
7
|
+
original_value = subject.send(property)
|
8
|
+
|
9
|
+
expect(subject.send(property)).to eq(value), "config property #{property} value did not match expectation"
|
10
|
+
ensure
|
11
|
+
# Make sure to set the original value at the end
|
12
|
+
subject.send("#{property}=", original_value)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Resteze
|
2
|
+
module Testing
|
3
|
+
module RSpec
|
4
|
+
module Object
|
5
|
+
extend RSpec::Matchers
|
6
|
+
|
7
|
+
# rubocop:disable Metrics/AbcSize
|
8
|
+
# rubocop:disable Naming/PredicatePrefix
|
9
|
+
def has_property(name, **options)
|
10
|
+
expect(subject.property?(name.to_sym)).to be(true), "Expected #{subject} to have property: #{name}"
|
11
|
+
assert_property_default(name, options[:default]) if options.key?(:default)
|
12
|
+
assert_property_translation(name, options[:from]) if options.key?(:from)
|
13
|
+
assert_property_transformed(name, transformed: options[:transformed]) if options.key?(:transformed)
|
14
|
+
assert_property_required(name, required: options[:required]) if options.key?(:required)
|
15
|
+
end
|
16
|
+
# rubocop:enable Naming/PredicatePrefix
|
17
|
+
|
18
|
+
def assert_property_transformed(name, transformed: true)
|
19
|
+
translation = subject.translations_hash.dig(subject.translations.key(name.to_sym), name.to_sym)
|
20
|
+
transformation_defined = translation.is_a?(Proc) || subject.transformation_exists?(name.to_sym)
|
21
|
+
|
22
|
+
if transformed
|
23
|
+
expect(transformation_defined).to be(true), "Expected #{subject} to transform property: #{name}"
|
24
|
+
else
|
25
|
+
expect(transformation_defined).to be(false), "Expected #{subject} not to transform property: #{name}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
# rubocop:enable Metrics/AbcSize
|
29
|
+
|
30
|
+
def assert_property_required(name, required: true)
|
31
|
+
if required
|
32
|
+
expect(subject.required?(name.to_sym)).to be(true), "Expected #{subject} to require property: #{name}"
|
33
|
+
else
|
34
|
+
expect(subject.required?(name.to_sym)).to be(false), "Expected #{subject} not to require property: #{name}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def assert_property_translation(name, from)
|
39
|
+
expect(subject.translations.key(name.to_sym)).to eq(from.to_sym),
|
40
|
+
"Expected #{subject} to map property #{name} from #{from}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def assert_property_default(name, default)
|
44
|
+
expect(subject.defaults[name.to_sym]).to eq(default), "Expected #{subject} to have default for property #{name}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/resteze/util.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
module Resteze
|
2
|
+
module Util
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def convert_to_object(data, object_class)
|
7
|
+
case data
|
8
|
+
when Array
|
9
|
+
data.map { |i| convert_to_object(i, object_class) }
|
10
|
+
when Hash
|
11
|
+
object_class.construct_from(object_class.object_key.present? ? { object_class.object_key => data } : data)
|
12
|
+
else
|
13
|
+
data
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def normalize_headers(headers)
|
18
|
+
headers.transform_keys { |key| capitalize_parts(key) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def normalize_id(id)
|
22
|
+
if id.is_a?(Hash)
|
23
|
+
params_hash = id.dup
|
24
|
+
id = params_hash.delete(:id)
|
25
|
+
else
|
26
|
+
params_hash = {}
|
27
|
+
end
|
28
|
+
|
29
|
+
[id.to_s.presence, params_hash]
|
30
|
+
end
|
31
|
+
|
32
|
+
def objects_to_ids(obj)
|
33
|
+
case obj
|
34
|
+
when ApiResource
|
35
|
+
obj.id
|
36
|
+
when Hash
|
37
|
+
res = {}
|
38
|
+
obj.each { |k, v| res[k] = objects_to_ids(v) unless v.nil? }
|
39
|
+
res
|
40
|
+
when Array
|
41
|
+
obj.map { |v| objects_to_ids(v) }
|
42
|
+
else
|
43
|
+
obj
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def capitalize_parts(str)
|
48
|
+
str.to_s.dasherize.split("-").reject(&:blank?).map(&:capitalize).join("-")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
extend ClassMethods
|
53
|
+
end
|
54
|
+
end
|
data/lib/resteze/version.rb
CHANGED
data/lib/resteze.rb
CHANGED
@@ -1,8 +1,127 @@
|
|
1
|
-
#
|
1
|
+
# Dependencies
|
2
|
+
require "action_dispatch/http/mime_type"
|
3
|
+
require "active_support/all"
|
4
|
+
require "faraday"
|
5
|
+
require "hashie"
|
6
|
+
require "logger"
|
2
7
|
|
3
8
|
require_relative "resteze/version"
|
4
9
|
|
10
|
+
# API Concerns
|
11
|
+
require "resteze/api_module"
|
12
|
+
require "resteze/request"
|
13
|
+
require "resteze/api_resource"
|
14
|
+
require "resteze/list"
|
15
|
+
require "resteze/save"
|
16
|
+
|
17
|
+
# API resource support classes
|
18
|
+
require "resteze/object"
|
19
|
+
|
20
|
+
# API Classes
|
21
|
+
require "resteze/client"
|
22
|
+
require "resteze/errors"
|
23
|
+
require "resteze/list_object"
|
24
|
+
require "resteze/response"
|
25
|
+
require "resteze/util"
|
26
|
+
|
27
|
+
# Middlewares
|
28
|
+
require "resteze/middleware/raise_error"
|
29
|
+
|
5
30
|
module Resteze
|
6
|
-
|
7
|
-
|
31
|
+
extend ActiveSupport::Concern
|
32
|
+
|
33
|
+
module ClassMethods
|
34
|
+
def configure
|
35
|
+
yield self
|
36
|
+
end
|
37
|
+
|
38
|
+
def default_service_path(_klass)
|
39
|
+
"/"
|
40
|
+
end
|
41
|
+
|
42
|
+
def default_api_version(_klass)
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def default_resource_slug(klass)
|
47
|
+
klass.name.demodulize.underscore.pluralize
|
48
|
+
end
|
49
|
+
|
50
|
+
def default_object_key(_klass)
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def default_list_key(_klass)
|
55
|
+
:data
|
56
|
+
end
|
57
|
+
|
58
|
+
def default_api_key(attribute)
|
59
|
+
attribute.to_s
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
extend ClassMethods
|
64
|
+
|
65
|
+
included do
|
66
|
+
class << self
|
67
|
+
attr_accessor :api_base,
|
68
|
+
:open_timeout,
|
69
|
+
:read_timeout,
|
70
|
+
:logger,
|
71
|
+
:proxy
|
72
|
+
end
|
73
|
+
|
74
|
+
configure do |config|
|
75
|
+
config.api_base = "http://example.com/"
|
76
|
+
config.open_timeout = 30
|
77
|
+
config.read_timeout = 60
|
78
|
+
config.logger = Logger.new($stdout)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Setup magic constants
|
82
|
+
const_set :Object, Class.new(Resteze::Object)
|
83
|
+
const_set :Client, Class.new(Resteze::Client)
|
84
|
+
const_set :Response, Class.new(Resteze::Response)
|
85
|
+
const_set :Error, Class.new(Resteze::Error)
|
86
|
+
|
87
|
+
Resteze::Error.subclasses.select { |klass| klass.name.start_with?("Resteze::") }.each do |error_class|
|
88
|
+
error_type = error_class.to_s.demodulize
|
89
|
+
const_set error_type, Class.new(error_class) unless const_defined?("#{self}::#{error_type}")
|
90
|
+
end
|
91
|
+
|
92
|
+
# Namespace other exceptions that we want to be able to catch and make sense of
|
93
|
+
# without needing lower level implementation details
|
94
|
+
const_set :NotImplementedError, Class.new(NotImplementedError)
|
95
|
+
const_set :ResourceNotFound, Class.new(Faraday::ResourceNotFound)
|
96
|
+
const_set :UnprocessableEntityError, Class.new(Faraday::UnprocessableEntityError)
|
97
|
+
const_set :ConflictError, Class.new(Faraday::ConflictError)
|
98
|
+
|
99
|
+
# Setup our Magic Constants
|
100
|
+
const_set(:ListObject, Class.new(Hashie::Array)).class_eval do
|
101
|
+
include ApiModule
|
102
|
+
prepend Resteze::ListObject
|
103
|
+
end
|
104
|
+
|
105
|
+
const_set(:ApiResource, Class.new(self::Object)).class_eval do
|
106
|
+
include Resteze::ApiResource
|
107
|
+
end
|
108
|
+
|
109
|
+
const_set(:Middleware, Module.new).module_eval do
|
110
|
+
const_set :RaiseError, Class.new(Resteze::Middleware::RaiseError)
|
111
|
+
end
|
112
|
+
|
113
|
+
const_set(:List, Module.new).module_eval do
|
114
|
+
extend ActiveSupport::Concern
|
115
|
+
include Resteze::List
|
116
|
+
end
|
117
|
+
|
118
|
+
const_set(:Save, Module.new).module_eval do
|
119
|
+
extend ActiveSupport::Concern
|
120
|
+
include Resteze::Save
|
121
|
+
end
|
122
|
+
|
123
|
+
const_set(:Util, Module.new).module_eval do
|
124
|
+
include Resteze::Util
|
125
|
+
end
|
126
|
+
end
|
8
127
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resteze
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- JD Hendrickson
|
8
|
-
bindir:
|
8
|
+
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 2025-08-12 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: actionpack
|
@@ -74,11 +74,33 @@ extra_rdoc_files: []
|
|
74
74
|
files:
|
75
75
|
- ".rubocop"
|
76
76
|
- ".rubocop.yml"
|
77
|
+
- ".ruby-version"
|
78
|
+
- CHANGELOG.md
|
77
79
|
- Guardfile
|
78
80
|
- LICENSE.txt
|
79
81
|
- README.md
|
80
82
|
- Rakefile
|
83
|
+
- assets/resteze.png
|
84
|
+
- assets/resteze.svg
|
81
85
|
- lib/resteze.rb
|
86
|
+
- lib/resteze/api_module.rb
|
87
|
+
- lib/resteze/api_resource.rb
|
88
|
+
- lib/resteze/client.rb
|
89
|
+
- lib/resteze/errors.rb
|
90
|
+
- lib/resteze/list.rb
|
91
|
+
- lib/resteze/list_object.rb
|
92
|
+
- lib/resteze/middleware/raise_error.rb
|
93
|
+
- lib/resteze/object.rb
|
94
|
+
- lib/resteze/request.rb
|
95
|
+
- lib/resteze/response.rb
|
96
|
+
- lib/resteze/save.rb
|
97
|
+
- lib/resteze/testing/minitest.rb
|
98
|
+
- lib/resteze/testing/minitest/configuration.rb
|
99
|
+
- lib/resteze/testing/minitest/object.rb
|
100
|
+
- lib/resteze/testing/rspec.rb
|
101
|
+
- lib/resteze/testing/rspec/configure.rb
|
102
|
+
- lib/resteze/testing/rspec/object.rb
|
103
|
+
- lib/resteze/util.rb
|
82
104
|
- lib/resteze/version.rb
|
83
105
|
- sig/resteze.rbs
|
84
106
|
licenses:
|
@@ -94,14 +116,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
116
|
requirements:
|
95
117
|
- - ">="
|
96
118
|
- !ruby/object:Gem::Version
|
97
|
-
version: 3.
|
119
|
+
version: 3.2.0
|
98
120
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
121
|
requirements:
|
100
122
|
- - ">="
|
101
123
|
- !ruby/object:Gem::Version
|
102
124
|
version: '0'
|
103
125
|
requirements: []
|
104
|
-
rubygems_version: 3.6.
|
126
|
+
rubygems_version: 3.6.2
|
105
127
|
specification_version: 4
|
106
128
|
summary: Resteze is a REST client library for Ruby.
|
107
129
|
test_files: []
|