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.
@@ -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,10 @@
1
+ require_relative "minitest/configuration"
2
+ require_relative "minitest/object"
3
+
4
+ module Resteze
5
+ module Testing
6
+ module Minitest
7
+ # Namespace for Minitest-specific testing helpers
8
+ end
9
+ end
10
+ 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
@@ -0,0 +1,10 @@
1
+ require_relative "rspec/configure"
2
+ require_relative "rspec/object"
3
+
4
+ module Resteze
5
+ module Testing
6
+ module RSpec
7
+ # Namespace for RSpec-specific testing helpers
8
+ end
9
+ end
10
+ end
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Resteze
4
- VERSION = "0.1.0"
4
+ VERSION = "0.3.1"
5
5
  end
data/lib/resteze.rb CHANGED
@@ -1,8 +1,127 @@
1
- # frozen_string_literal: true
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
- class Error < StandardError; end
7
- # Your code goes here...
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.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - JD Hendrickson
8
- bindir: exe
8
+ bindir: bin
9
9
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
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.1.0
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.9
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: []