json_resource 1.0.0 → 1.1.1

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: 9c5d0ad6feca66b6bd7524037d69edf9da40ba45c5f25a6441ef4543d174e5ad
4
+ data.tar.gz: 6ee0efc65381f5243b3da05ef710dc7a8ea6e296708e2a4224c680b728fb9331
5
5
  SHA512:
6
- metadata.gz: 1a8a3aae1d4e7b21df4e09cc5d8da6f807219e6fc3841c02ca200d9bce621aa222f5e4caa1ee61b190c6041d2b1269674dcaf9b3453e4d8ccdebf3bc41e3e518
7
- data.tar.gz: ab5f72f1a266e1ba3e8ae993d951339c9f63c66a5960e241968931343233ce2bafdcf8667eb58378589e698b628573d0f4b2f9b54d427693667095c574348d5b
6
+ metadata.gz: f534f05c6e7748186cfb3373c3b55c5891d0c572be08b917f380d4cf49443a60dbdda258a3dda9778edd9b623eb4f4d45cff2c5223423c8ad450cacfde050030
7
+ data.tar.gz: 0f7703523f9b619ce117fb889fd6f9eba4738a6ceeed9d5e043edc54c1c057f25ba4d788da958b2a7121ddd93a5688787477618f0a247ff294305b804dc89a77
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 1.1.0 – 2023-11-01
2
+
3
+ - Improve BigDecimal conversion
4
+
1
5
  ## 1.0.0
2
6
 
3
7
  - 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
 
@@ -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
@@ -1,3 +1,3 @@
1
1
  module JsonResource
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.1'
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.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthias Grosser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-10 00:00:00.000000000 Z
11
+ date: 2023-11-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -52,7 +52,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
52
52
  requirements:
53
53
  - - ">="
54
54
  - !ruby/object:Gem::Version
55
- version: 2.6.0
55
+ version: 2.7.0
56
56
  required_rubygems_version: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - ">="