primalize 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +13 -0
- data/lib/primalize/many.rb +21 -0
- data/lib/primalize/single.rb +96 -13
- data/lib/primalize/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 211551a4a7fc66702f544d35f053e4e9f65d1fe1
|
4
|
+
data.tar.gz: b6f715a19f9b32fae1b4c025ae195ed1643faf65
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1557c13cf41e2924453083053dd5de8b08b258cbdca01a2f55cf9d72f2f1a6ab048bb94fe564467346daea9292f8a436fd932db6dca4fc989d4b1a8aebf601ab
|
7
|
+
data.tar.gz: 133145cfb6bca06af9fd920eca885aa16707ca2af8b49e7c4c059112d65052232af87ab6a7e6049d701497c143e15008a22ae8be8fe5a6b1e18e756518e63a2e
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -112,6 +112,19 @@ class ShipmentSerializer < Primalize::Single
|
|
112
112
|
end
|
113
113
|
```
|
114
114
|
|
115
|
+
### Type Checking
|
116
|
+
|
117
|
+
By default, subclasses of `Primalize::Single` will raise an `ArgumentError` if there is a mismatch between the types declared in its `attributes` call and what is passed in to be primalized. In production, you might not want that to happen, so you can change that in your production config:
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
Primalize::Single.type_mismatch_handler = proc do |attr, type, value|
|
121
|
+
msg = "Type mismatch: #{attr} is expected to be #{type.inspect}, but is a #{value.inspect} - " +
|
122
|
+
caller.grep(Regexp.new(Rails.root))
|
123
|
+
|
124
|
+
Slack.notify '#bugs', msg
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
115
128
|
## Development
|
116
129
|
|
117
130
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/primalize/many.rb
CHANGED
@@ -28,6 +28,10 @@ module Primalize
|
|
28
28
|
define_singleton_method :inspect do
|
29
29
|
"enumerable(#{serializer_class.inspect})"
|
30
30
|
end
|
31
|
+
|
32
|
+
define_singleton_method :attributes do
|
33
|
+
serializer_class.attributes
|
34
|
+
end
|
31
35
|
end
|
32
36
|
end
|
33
37
|
|
@@ -86,5 +90,22 @@ module Primalize
|
|
86
90
|
def to_json
|
87
91
|
call.to_json
|
88
92
|
end
|
93
|
+
|
94
|
+
def to_csv attr
|
95
|
+
CSV.generate do |csv|
|
96
|
+
result = call[attr]
|
97
|
+
|
98
|
+
csv << self.class.attributes[attr].attributes.keys
|
99
|
+
|
100
|
+
case result
|
101
|
+
when Hash
|
102
|
+
csv << result.values
|
103
|
+
when Array
|
104
|
+
result.each do |hash|
|
105
|
+
csv << hash.values
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
89
110
|
end
|
90
111
|
end
|
data/lib/primalize/single.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'date'
|
3
|
+
require 'csv'
|
3
4
|
|
4
5
|
module Primalize
|
5
6
|
class Single
|
6
|
-
@type_mismatch_handler = proc do |attr, type, value|
|
7
|
-
raise TypeError, "#{
|
7
|
+
@type_mismatch_handler = proc do |klass, attr, type, value|
|
8
|
+
raise TypeError, "#{klass}##{attr} is specified as #{type.inspect}, but is #{value.inspect}"
|
8
9
|
end
|
9
10
|
|
10
11
|
class << self
|
@@ -24,12 +25,7 @@ module Primalize
|
|
24
25
|
|
25
26
|
attrs.each do |attr, type|
|
26
27
|
define_method attr do
|
27
|
-
|
28
|
-
if type === value
|
29
|
-
value
|
30
|
-
else
|
31
|
-
self.class.type_mismatch_handler.call attr, type, value
|
32
|
-
end
|
28
|
+
type.coerce(object.public_send(attr))
|
33
29
|
end
|
34
30
|
end
|
35
31
|
end
|
@@ -58,6 +54,10 @@ module Primalize
|
|
58
54
|
Float.new(&coerce)
|
59
55
|
end
|
60
56
|
|
57
|
+
def number &coerce
|
58
|
+
Number.new(&coerce)
|
59
|
+
end
|
60
|
+
|
61
61
|
def optional *types, &coerce
|
62
62
|
Optional.new(types, &coerce)
|
63
63
|
end
|
@@ -70,6 +70,14 @@ module Primalize
|
|
70
70
|
Timestamp.new(&coerce)
|
71
71
|
end
|
72
72
|
|
73
|
+
def any *types, &coerce
|
74
|
+
Any.new(types, &coerce)
|
75
|
+
end
|
76
|
+
|
77
|
+
def primalize primalizer, &coerce
|
78
|
+
Primalizer.new(primalizer, &coerce)
|
79
|
+
end
|
80
|
+
|
73
81
|
def type_mismatch_handler= handler
|
74
82
|
@type_mismatch_handler = handler
|
75
83
|
end
|
@@ -90,20 +98,42 @@ module Primalize
|
|
90
98
|
attr_reader :object
|
91
99
|
|
92
100
|
def initialize object
|
101
|
+
raise ArgumentError, "#{self.class.inspect} cannot serialize `nil'" if object.nil?
|
93
102
|
@object = object
|
94
103
|
end
|
95
104
|
|
96
105
|
def call
|
97
|
-
self.class.attributes.each_with_object({}) do |(attr,
|
98
|
-
|
106
|
+
self.class.attributes.each_with_object({}) do |(attr, type), hash|
|
107
|
+
value = public_send(attr)
|
108
|
+
|
109
|
+
if type === value
|
110
|
+
hash[attr] = value
|
111
|
+
else
|
112
|
+
self.class.type_mismatch_handler.call self.class, attr, type, value
|
113
|
+
end
|
99
114
|
end
|
100
115
|
end
|
101
116
|
|
102
|
-
#
|
117
|
+
# CONVERSION
|
103
118
|
|
104
|
-
|
119
|
+
def to_json
|
120
|
+
call.to_json
|
121
|
+
end
|
122
|
+
|
123
|
+
def csv_headers
|
124
|
+
self.class.attributes.keys.map(&:to_s)
|
125
|
+
end
|
126
|
+
|
127
|
+
def to_csv
|
128
|
+
hash = call
|
129
|
+
CSV.generate { |csv| csv << hash.values }
|
130
|
+
end
|
131
|
+
|
132
|
+
# TYPES
|
105
133
|
|
106
134
|
module Type
|
135
|
+
DEFAULT_COERCION = proc { |arg| arg } # Don't coerce by default
|
136
|
+
|
107
137
|
def coerce *args
|
108
138
|
(@coercion || DEFAULT_COERCION).call(*args)
|
109
139
|
end
|
@@ -141,6 +171,18 @@ module Primalize
|
|
141
171
|
end
|
142
172
|
end
|
143
173
|
|
174
|
+
class Number
|
175
|
+
include Type
|
176
|
+
|
177
|
+
def === value
|
178
|
+
::Numeric === value
|
179
|
+
end
|
180
|
+
|
181
|
+
def inspect
|
182
|
+
'number'
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
144
186
|
class String
|
145
187
|
include Type
|
146
188
|
|
@@ -203,7 +245,7 @@ module Primalize
|
|
203
245
|
|
204
246
|
def initialize types, &coercion
|
205
247
|
@types = types
|
206
|
-
@coercion = coercion
|
248
|
+
@coercion = coercion
|
207
249
|
end
|
208
250
|
|
209
251
|
def === value
|
@@ -233,6 +275,30 @@ module Primalize
|
|
233
275
|
end
|
234
276
|
end
|
235
277
|
|
278
|
+
class Primalizer
|
279
|
+
include Type
|
280
|
+
|
281
|
+
def initialize primalizer, &coercion
|
282
|
+
@primalizer = primalizer
|
283
|
+
@coercion = coercion || proc do |obj|
|
284
|
+
# FIXME: this is dumb
|
285
|
+
begin
|
286
|
+
primalizer.new(obj).call
|
287
|
+
rescue ArgumentError => e
|
288
|
+
raise TypeError.new(e)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def === value
|
294
|
+
true
|
295
|
+
end
|
296
|
+
|
297
|
+
def inspect
|
298
|
+
"primalize(#{@primalizer.inspect})"
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
236
302
|
class Optional
|
237
303
|
include Type
|
238
304
|
|
@@ -249,5 +315,22 @@ module Primalize
|
|
249
315
|
"optional(#{@types.map(&:inspect).join(', ')})"
|
250
316
|
end
|
251
317
|
end
|
318
|
+
|
319
|
+
class Any
|
320
|
+
include Type
|
321
|
+
|
322
|
+
def initialize types, &coercion
|
323
|
+
@types = types
|
324
|
+
end
|
325
|
+
|
326
|
+
def === value
|
327
|
+
@types.empty? || @types.any? { |type| type === value }
|
328
|
+
end
|
329
|
+
|
330
|
+
def inspect
|
331
|
+
params = "(#{@types.map(&:inspect).join(', ')})"
|
332
|
+
"any#{@types.empty? ? nil : params}"
|
333
|
+
end
|
334
|
+
end
|
252
335
|
end
|
253
336
|
end
|
data/lib/primalize/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: primalize
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jamie Gaskins
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-09-
|
11
|
+
date: 2017-09-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|