json_resource 1.0.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dbada0c6c6821280079957d75f002a39fa338c6566a4daf7cda3650b98fb29fd
4
- data.tar.gz: a232cf53b5e86dd6e9df328786c5db0ab150747284e11682d5b51bf426fef46c
3
+ metadata.gz: f26ed85c08a888e816d5bece3c37bd373c6fb61df4042e80cd0bcb371dbfd23a
4
+ data.tar.gz: 48bc07b4f66618f635591dc24de3195ca19eb6fb8a2a253b6fe9d32f1de6ac8b
5
5
  SHA512:
6
- metadata.gz: 1a8a3aae1d4e7b21df4e09cc5d8da6f807219e6fc3841c02ca200d9bce621aa222f5e4caa1ee61b190c6041d2b1269674dcaf9b3453e4d8ccdebf3bc41e3e518
7
- data.tar.gz: ab5f72f1a266e1ba3e8ae993d951339c9f63c66a5960e241968931343233ce2bafdcf8667eb58378589e698b628573d0f4b2f9b54d427693667095c574348d5b
6
+ metadata.gz: c041eb4bf88f877a95f2330ec8d3c066b62621290d3f30a1121216c9eb57d1625282c5d3c0bfc34f23bfe96e345a7cbf43d7f3b5f72c6299a450f6f862983a0c
7
+ data.tar.gz: dd98b1e2d0e4fd314e848b3b777a31d1c5a33791c4f161e0dc452fdfcb9da0e6d7ed7c5beaf4115598bcdf6b6d12e2669bf6660300c9223b693ad7dafd7f12d7
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 1.2.0 - 2024-11-06
2
+
3
+ - Add underscore inflection name
4
+ - Fix has_attributes
5
+
6
+ ## 1.1.0 – 2023-11-01
7
+
8
+ - Improve BigDecimal conversion
9
+
1
10
  ## 1.0.0
2
11
 
3
12
  - First release
data/README.md CHANGED
@@ -62,3 +62,68 @@ posts.first.body => 'Lorem ipsum'
62
62
  posts.first.status_text => 'published'
63
63
  posts.first.comments.first.author => 'Mr. Spock'
64
64
  ```
65
+
66
+ ## Instantiation
67
+
68
+ To instantiate collections, use `collection_from_json` on a JSON array.
69
+
70
+ To instantiate single objects, use `from_json` on a JSON hash.
71
+
72
+
73
+ ## Field types
74
+
75
+ Attributes can have one of the following types:
76
+
77
+ | Type | Conversion | Options |
78
+ | ----------- | ------------------- | ------------------------- |
79
+ | `:string` | `value` | |
80
+ | `:integer` | `value.to_i` | |
81
+ | `:float` | `value.to_f` | |
82
+ | `:boolean` | any of `[true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON']` | |
83
+ | `:decimal` | direct, or `to_d` | `:precision`, `:scale` |
84
+ | `:date` | `Date.parse` | |
85
+ | `:time` | `Time.parse` | |
86
+
87
+
88
+ ## Extracting data
89
+
90
+ Sometimes, APIs return data wrapped within arrays of hashes of arrays etc:
91
+
92
+ ```json
93
+ {
94
+ "data": [
95
+ {
96
+ "status": "ok"
97
+ },
98
+ {
99
+ "planets": [
100
+ {
101
+ "name": "Earth",
102
+ "mass": 5.9722E+24,
103
+ "orbit": 1.000
104
+ },
105
+ {
106
+ "name": "Jupiter",
107
+ "mass": 1.8990E+27,
108
+ "orbit": 5.205
109
+ }
110
+ ]
111
+ }
112
+ ]
113
+ }
114
+ ```
115
+
116
+ ```ruby
117
+ class Planet
118
+ include JsonResource::Model
119
+
120
+ attribute :name, type: :string
121
+ attribute :mass, type: :decimal, precision: 10, scale: 4
122
+ end
123
+ ```
124
+
125
+ To dig for this data, a call-sequence can be provided as the `root` option.
126
+
127
+ ```ruby
128
+ planets = Planet.collection_from_json(json, root: %w[data [1] planets])
129
+ ```
@@ -3,6 +3,7 @@ module JsonResource
3
3
 
4
4
  module Model
5
5
  TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON'].to_set
6
+ BIGDECIMAL_PRECISION = 18
6
7
 
7
8
  def self.included(base)
8
9
  base.extend ClassMethods
@@ -23,7 +24,7 @@ module JsonResource
23
24
  if path = attribute_path(name)
24
25
  value = json_dig(json, *path)
25
26
  if !value.nil? && type = attribute_type(name)
26
- value = cast_to(type, value)
27
+ value = cast_to(type, value, name)
27
28
  end
28
29
  attrs[name] = value
29
30
  end
@@ -46,7 +47,7 @@ module JsonResource
46
47
 
47
48
  def collection_from_json(obj, defaults: {}, root: nil)
48
49
  json = parse(obj)
49
- json = json_dig(json, root) if root
50
+ json = json_dig(json, *root) if root
50
51
  json.map { |hsh| from_json(hsh, defaults: defaults) }.compact
51
52
  end
52
53
 
@@ -67,9 +68,9 @@ module JsonResource
67
68
  attribute_accessor_method name
68
69
  end
69
70
 
70
- def attributes(*args)
71
+ def has_attributes(*args)
71
72
  options = args.extract_options!
72
- args.each { |arg| has_attribute arg, options }
73
+ args.each { |arg| attribute arg, options }
73
74
  end
74
75
 
75
76
  def has_object(name, options = {})
@@ -95,16 +96,20 @@ module JsonResource
95
96
  end
96
97
 
97
98
  [:attribute, :object, :collection].each do |method_name|
99
+ define_method "#{method_name}_options" do |name|
100
+ send(method_name.to_s.pluralize).try(:[], name)
101
+ end
102
+
98
103
  define_method "#{method_name}_path" do |name|
99
- options = send(method_name.to_s.pluralize)
100
- Array(options[name].try(:[], :path)).presence || [inflect(name)]
104
+ options = send("#{method_name}_options", name)
105
+ Array(options.try(:[], :path)).presence || [inflect(name)]
101
106
  end
102
107
  end
103
108
 
104
109
  def attribute_type(name)
105
110
  attributes[name] && attributes[name][:type]
106
111
  end
107
-
112
+
108
113
  def object_class(name)
109
114
  if objects[name] && class_name = objects[name][:class_name]
110
115
  class_name.constantize
@@ -121,13 +126,13 @@ module JsonResource
121
126
  end
122
127
  end
123
128
 
124
- def cast_to(type, value) # only called for non-nil values
129
+ def cast_to(type, value, name) # only called for non-nil values
125
130
  case type
126
131
  when :string then value
127
132
  when :integer then value.to_i
128
133
  when :float then value.to_f
129
134
  when :boolean then cast_to_boolean(value)
130
- when :decimal then BigDecimal(value)
135
+ when :decimal then cast_to_big_decimal(value, **attribute_options(name))
131
136
  when :date then value.presence && Date.parse(value)
132
137
  when :time then value.presence && Time.parse(value)
133
138
  else
@@ -142,6 +147,26 @@ module JsonResource
142
147
  TRUE_VALUES.include?(value)
143
148
  end
144
149
  end
150
+
151
+ def cast_to_big_decimal(value, scale: nil, precision: nil, **)
152
+ cast_value = case value
153
+ when ::Float
154
+ precision ||= BIGDECIMAL_PRECISION
155
+ float_precision = precision.to_i > ::Float::DIG + 1 ? ::Float::DIG + 1 : precision.to_i
156
+ BigDecimal(value, float_precision)
157
+ when ::Numeric
158
+ BigDecimal(value, precision || BIGDECIMAL_PRECISION)
159
+ when ::String
160
+ begin
161
+ value.to_d
162
+ rescue ArgumentError
163
+ BigDecimal(0)
164
+ end
165
+ else
166
+ value.respond_to?(:to_d) ? value.to_d : BigDecimal(value.to_s)
167
+ end
168
+ scale ? cast_value.round(scale) : cast_value
169
+ end
145
170
 
146
171
  def parse(obj)
147
172
  case obj
@@ -161,7 +186,7 @@ module JsonResource
161
186
  string.camelcase(:upper)
162
187
  when :dasherize
163
188
  string.underscore.dasherize
164
- when nil
189
+ when nil, :underscore
165
190
  string.underscore
166
191
  else
167
192
  string.public_send(inflection)
@@ -202,7 +202,19 @@ module JsonResource
202
202
  def symbolize_keys
203
203
  transform_keys(&:to_sym)
204
204
  end
205
-
205
+
206
+ end
207
+
208
+ refine Array do
209
+
210
+ def extract_options!
211
+ if last.is_a?(Hash) && last.instance_of?(Hash)
212
+ pop
213
+ else
214
+ {}
215
+ end
216
+ end
217
+
206
218
  end
207
219
 
208
220
  end
@@ -1,3 +1,3 @@
1
1
  module JsonResource
2
- VERSION = '1.0.0'
2
+ VERSION = '1.2.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json_resource
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthias Grosser
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-10 00:00:00.000000000 Z
11
+ date: 2024-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -24,7 +24,21 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
- description:
27
+ - !ruby/object:Gem::Dependency
28
+ name: bigdecimal
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description:
28
42
  email:
29
43
  - mtgrosser@gmx.net
30
44
  executables: []
@@ -44,7 +58,7 @@ homepage: https://github.com/mtgrosser/json_resource
44
58
  licenses:
45
59
  - MIT
46
60
  metadata: {}
47
- post_install_message:
61
+ post_install_message:
48
62
  rdoc_options: []
49
63
  require_paths:
50
64
  - lib
@@ -52,15 +66,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
52
66
  requirements:
53
67
  - - ">="
54
68
  - !ruby/object:Gem::Version
55
- version: 2.6.0
69
+ version: 3.2.0
56
70
  required_rubygems_version: !ruby/object:Gem::Requirement
57
71
  requirements:
58
72
  - - ">="
59
73
  - !ruby/object:Gem::Version
60
74
  version: '0'
61
75
  requirements: []
62
- rubygems_version: 3.1.4
63
- signing_key:
76
+ rubygems_version: 3.5.11
77
+ signing_key:
64
78
  specification_version: 4
65
79
  summary: Create Ruby objects from JSON data
66
80
  test_files: []