fulfil_api 0.2.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/lib/fulfil_api/configuration.rb +14 -34
- data/lib/fulfil_api/resource/attribute_assignable.rb +22 -2
- data/lib/fulfil_api/resource/comparable.rb +20 -0
- data/lib/fulfil_api/resource/serializable.rb +53 -0
- data/lib/fulfil_api/resource.rb +2 -0
- data/lib/fulfil_api/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31bfb876f7d82e4d803cbacf7b3628f5acb66c086188e1c56c50a37dfe6cb6f4
|
4
|
+
data.tar.gz: db1418268779073af449b43f71ccc47a8a4ad1db92c3261b7d22d9821f5155e0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5cdefd3a083ef390084db3a04276c49c02243b0cf39b52f9c6146657f712f68251e3087f636d789978536f106d1a59f1b3c18f014ebc2c6330501654cc94a08a
|
7
|
+
data.tar.gz: 0522da7f4f12ebf1753df8512a716a7c496c11d9f0740ea599ecbfc742b7ef026ca4324769d6bba5f2d37ee16ee4cb963baa5d318d46ea9020538c390fe98e02
|
@@ -16,8 +16,6 @@ module FulfilApi
|
|
16
16
|
# @param options [Hash, nil] An optional list of configuration options.
|
17
17
|
# Each key in the hash should correspond to a configuration attribute.
|
18
18
|
def initialize(options = {})
|
19
|
-
@mutex = Mutex.new
|
20
|
-
|
21
19
|
# Assigns the optional configuration options
|
22
20
|
options.each_pair do |key, value|
|
23
21
|
send(:"#{key}=", value) if respond_to?(:"#{key}=")
|
@@ -27,25 +25,6 @@ module FulfilApi
|
|
27
25
|
set_default_options
|
28
26
|
end
|
29
27
|
|
30
|
-
# Provides thread-safe access to missing methods, allowing dynamic handling of configuration options.
|
31
|
-
#
|
32
|
-
# @param method [Symbol] The method name.
|
33
|
-
# @param args [Array] The arguments passed to the method.
|
34
|
-
# @param block [Proc] An optional block passed to the method.
|
35
|
-
# @return [void]
|
36
|
-
def method_missing(method, *args, &block)
|
37
|
-
@mutex.synchronize { super }
|
38
|
-
end
|
39
|
-
|
40
|
-
# Ensures that the object responds correctly to methods handled by method_missing.
|
41
|
-
#
|
42
|
-
# @param method [Symbol] The method name.
|
43
|
-
# @param include_private [Boolean] Whether to include private methods.
|
44
|
-
# @return [Boolean] Whether the object responds to the method.
|
45
|
-
def respond_to_missing?(method, include_private = false)
|
46
|
-
@mutex.synchronize { super }
|
47
|
-
end
|
48
|
-
|
49
28
|
private
|
50
29
|
|
51
30
|
# Sets the default options for the gem configuration.
|
@@ -61,13 +40,12 @@ module FulfilApi
|
|
61
40
|
end
|
62
41
|
|
63
42
|
@configuration = Configuration.new
|
64
|
-
@configuration_mutex = Mutex.new
|
65
43
|
|
66
44
|
# Provides thread-safe access to the gem's configuration.
|
67
45
|
#
|
68
46
|
# @return [Fulfil::Configuration] The current configuration object.
|
69
47
|
def self.configuration
|
70
|
-
|
48
|
+
Thread.current[:fulfil_api_configuration] ||= Configuration.new
|
71
49
|
end
|
72
50
|
|
73
51
|
# Allows the configuration of the gem in a thread-safe manner.
|
@@ -75,23 +53,25 @@ module FulfilApi
|
|
75
53
|
# @yieldparam [Fulfil::Configuration] config The current configuration object.
|
76
54
|
# @return [void]
|
77
55
|
def self.configure
|
78
|
-
|
56
|
+
yield(configuration)
|
79
57
|
end
|
80
58
|
|
81
59
|
# Overwrites the configuration with the newly provided configuration options.
|
82
60
|
#
|
83
61
|
# @param options [Hash, Fulfil::Configuration] A list of configuration options for the gem.
|
84
62
|
# @return [Fulfil::Configuration] The updated configuration object.
|
85
|
-
def self.configuration=(options_or_configuration)
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
63
|
+
def self.configuration=(options_or_configuration) # rubocop:disable Metrics/MethodLength
|
64
|
+
Thread.current[:fulfil_api_configuration] =
|
65
|
+
case options_or_configuration
|
66
|
+
when Hash
|
67
|
+
config = Configuration.new
|
68
|
+
options_or_configuration.each { |key, value| config.send(:"#{key}=", value) }
|
69
|
+
config
|
70
|
+
when Configuration
|
71
|
+
options_or_configuration
|
72
|
+
else
|
73
|
+
raise ArgumentError, "Expected Hash or Configuration, got #{options_or_configuration.class} instead"
|
93
74
|
end
|
94
|
-
end
|
95
75
|
end
|
96
76
|
|
97
77
|
# Temporarily applies the provided configuration options within a block,
|
@@ -107,6 +87,6 @@ module FulfilApi
|
|
107
87
|
yield
|
108
88
|
ensure
|
109
89
|
# Revert to the original configuration
|
110
|
-
|
90
|
+
Thread.current[:fulfil_api_configuration] = original_configuration
|
111
91
|
end
|
112
92
|
end
|
@@ -22,11 +22,31 @@ module FulfilApi
|
|
22
22
|
# @param name [String, Symbol] The attribute name
|
23
23
|
# @param value [Any] The attribute value
|
24
24
|
# @return [Hash] The resource attributes
|
25
|
-
def assign_attribute(name, value)
|
25
|
+
def assign_attribute(name, value) # rubocop:disable Metrics/MethodLength
|
26
26
|
attribute = build_attribute(name, value)
|
27
27
|
attribute.deep_stringify_keys!
|
28
28
|
|
29
|
-
|
29
|
+
# NOTE: Fulfil will assign the ID of a nested resource to its own namespace.
|
30
|
+
# This leads to conflicts when we're trying to parse the returned fields
|
31
|
+
# from the API.
|
32
|
+
#
|
33
|
+
# To address this problem, we're manually handling these cases. We're dealing
|
34
|
+
# with a nested relation when one of the values is an integer and the other
|
35
|
+
# is an hash.
|
36
|
+
#
|
37
|
+
# @example a nested relation
|
38
|
+
#
|
39
|
+
# $ resource.assign_attributes({ "warehouse.name" => "Toronto", "warehouse" => 10 })
|
40
|
+
# => <FulfilApi::Resource @attributes={"warehouse" => { "id" => 10, "name" => "Toronto" }} />
|
41
|
+
@attributes = @attributes.deep_merge(attribute) do |_key, current_value, other_value|
|
42
|
+
if current_value.is_a?(Integer) && other_value.is_a?(Hash)
|
43
|
+
{ "id" => current_value }.deep_merge(other_value)
|
44
|
+
elsif current_value.is_a?(Hash) && other_value.is_a?(Integer)
|
45
|
+
current_value.deep_merge({ "id" => other_value })
|
46
|
+
else
|
47
|
+
other_value
|
48
|
+
end
|
49
|
+
end
|
30
50
|
end
|
31
51
|
|
32
52
|
private
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FulfilApi
|
4
|
+
class Resource
|
5
|
+
module Comparable
|
6
|
+
def ==(other)
|
7
|
+
other.is_a?(FulfilApi::Resource) &&
|
8
|
+
other.hash == hash
|
9
|
+
end
|
10
|
+
|
11
|
+
def eql?(other)
|
12
|
+
self == other
|
13
|
+
end
|
14
|
+
|
15
|
+
def hash
|
16
|
+
@attributes.hash
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FulfilApi
|
4
|
+
class Resource
|
5
|
+
module Serializable
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
class_methods do
|
9
|
+
# Turns a JSON string into a {FulfilApi::Resource}.
|
10
|
+
#
|
11
|
+
# @note it's required to include the name of the model as part of the JSON
|
12
|
+
# string too. Otherwise, you will encounter a naming error when attempting
|
13
|
+
# to turn the JSON into a {FulfilApi::Resource}
|
14
|
+
#
|
15
|
+
# @param json [String] The JSONified data
|
16
|
+
# @param root_included [true, false] When using Rails, one can include
|
17
|
+
# @return [FulfilApi::Resource]
|
18
|
+
def from_json(json, root_included: false)
|
19
|
+
attributes = JSON.parse(json)
|
20
|
+
attributes = attributes.values.first if root_included
|
21
|
+
|
22
|
+
new(attributes)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Overwrites the default {#as_json} method because {ActiveModel} will nest
|
27
|
+
# the attributes when the model is transformed to JSON.
|
28
|
+
#
|
29
|
+
# @param options [Hash, nil] An optional list of options
|
30
|
+
# @return [Hash] A set of attributes available to be JSONified.
|
31
|
+
def as_json(options = nil)
|
32
|
+
# NOTE: We're including the model name by default. Otherwise, we can't use
|
33
|
+
# the {.from_json} method to parse it when reading from JSON.
|
34
|
+
hash = to_h.merge("model_name" => @model_name)
|
35
|
+
|
36
|
+
case options
|
37
|
+
in { root: }
|
38
|
+
{ root => hash }
|
39
|
+
else
|
40
|
+
hash
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Turns the {Resource} into a JSON object.
|
45
|
+
#
|
46
|
+
# @param options [Hash, nil] An optional list of options
|
47
|
+
# @return [String] The JSONified resource data
|
48
|
+
def to_json(options = nil)
|
49
|
+
as_json(options).to_json
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/fulfil_api/resource.rb
CHANGED
@@ -5,7 +5,9 @@ module FulfilApi
|
|
5
5
|
# endpoints of Fulfil.
|
6
6
|
class Resource
|
7
7
|
include AttributeAssignable
|
8
|
+
include Comparable
|
8
9
|
include Persistable
|
10
|
+
include Serializable
|
9
11
|
|
10
12
|
# The model name is required to be able to build the API endpoint to
|
11
13
|
# perform the search/read/count HTTP requests.
|
data/lib/fulfil_api/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fulfil_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefan Vermaas
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-04-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -95,8 +95,10 @@ files:
|
|
95
95
|
- lib/fulfil_api/resource.rb
|
96
96
|
- lib/fulfil_api/resource/attribute_assignable.rb
|
97
97
|
- lib/fulfil_api/resource/attribute_type.rb
|
98
|
+
- lib/fulfil_api/resource/comparable.rb
|
98
99
|
- lib/fulfil_api/resource/errors.rb
|
99
100
|
- lib/fulfil_api/resource/persistable.rb
|
101
|
+
- lib/fulfil_api/resource/serializable.rb
|
100
102
|
- lib/fulfil_api/test_helper.rb
|
101
103
|
- lib/fulfil_api/version.rb
|
102
104
|
- sig/fulfil_api.rbs
|