iso-deserializer 0.8.0
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 +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +32 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +55 -0
- data/MIT-LICENSE +20 -0
- data/README.md +641 -0
- data/Rakefile +11 -0
- data/deserializer.gemspec +25 -0
- data/gemfiles/4.0.gemfile +8 -0
- data/gemfiles/5.0.gemfile +8 -0
- data/gemfiles/6.0.gemfile +8 -0
- data/lib/deserializer/attributable.rb +54 -0
- data/lib/deserializer/attribute/association.rb +12 -0
- data/lib/deserializer/attribute/attribute.rb +20 -0
- data/lib/deserializer/attribute/base.rb +49 -0
- data/lib/deserializer/attribute/has_many_association.rb +14 -0
- data/lib/deserializer/attribute/has_one_association.rb +35 -0
- data/lib/deserializer/attribute/nested_association.rb +10 -0
- data/lib/deserializer/attribute/value_attribute.rb +24 -0
- data/lib/deserializer/attribute.rb +11 -0
- data/lib/deserializer/base.rb +56 -0
- data/lib/deserializer/deserializer_error.rb +12 -0
- data/lib/deserializer/version.rb +3 -0
- data/lib/deserializer.rb +12 -0
- data/test/lib/deserializers.rb +148 -0
- data/test/minitest_helper.rb +14 -0
- data/test/unit/deserializer_error_test.rb +12 -0
- data/test/unit/deserializer_test.rb +200 -0
- metadata +118 -0
data/README.md
ADDED
@@ -0,0 +1,641 @@
|
|
1
|
+
# Deserializer
|
2
|
+
## Features
|
3
|
+
- Hash transformation and sanitization
|
4
|
+
- Deserialization of complex parameters into a hash that an AR model can take
|
5
|
+
- Avoid having multiple definitions in fragile arrays when using strong params
|
6
|
+
- Easy create and update from JSON without writing heavy controllers
|
7
|
+
- [ActiveModel::Serializer](https://github.com/rails-api/active_model_serializers)-like interface and conventions
|
8
|
+
|
9
|
+
## Problem
|
10
|
+
Let's say we have an API with an endpoint that takes this JSON:
|
11
|
+
|
12
|
+
```json
|
13
|
+
{
|
14
|
+
"restaurant_id" : 13,
|
15
|
+
"user_id" : 6,
|
16
|
+
"dish_name" : "risotto con funghi",
|
17
|
+
"description" : "repulsive beyond belief",
|
18
|
+
"ratings" : {
|
19
|
+
"taste" : "terrible",
|
20
|
+
"color" : "horrendous",
|
21
|
+
"texture" : "vile",
|
22
|
+
"smell" : "delightful, somehow"
|
23
|
+
}
|
24
|
+
}
|
25
|
+
```
|
26
|
+
|
27
|
+
But this goes into a flat DishReview model:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
t.belongs_to :restaurant
|
31
|
+
t.belongs_to :user
|
32
|
+
t.string :name # field name different from API (dish_name)
|
33
|
+
t.string :description
|
34
|
+
t.string :taste
|
35
|
+
t.string :color
|
36
|
+
t.string :texture
|
37
|
+
t.string :smell
|
38
|
+
```
|
39
|
+
|
40
|
+
### Solution (No `Deserializer`)
|
41
|
+
Permit some params, do some parsing and feed that into `DishReview.new`:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
class DishReviewController < BaseController
|
45
|
+
|
46
|
+
def create
|
47
|
+
review_params = get_review_params(params)
|
48
|
+
@review = DishReview.new(review_params)
|
49
|
+
if @review.save
|
50
|
+
# return review
|
51
|
+
else
|
52
|
+
# return sad errors splody
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# rest of RUD
|
57
|
+
|
58
|
+
protected
|
59
|
+
|
60
|
+
def permitted_params
|
61
|
+
[
|
62
|
+
:restaurant_id,
|
63
|
+
:user_id
|
64
|
+
:dish_name,
|
65
|
+
:description,
|
66
|
+
:taste,
|
67
|
+
:color,
|
68
|
+
:texture,
|
69
|
+
:smell
|
70
|
+
]
|
71
|
+
end
|
72
|
+
|
73
|
+
def get_review_params(params)
|
74
|
+
review_params = params.require(:review)
|
75
|
+
|
76
|
+
review_params[:name] ||= review_params.delete(:dish_name)
|
77
|
+
|
78
|
+
ratings = review_params.delete(:ratings)
|
79
|
+
if (ratings.present?)
|
80
|
+
ratings.each{|rating, value| review_params[rating] = value if valid_rating?(rating) }
|
81
|
+
end
|
82
|
+
|
83
|
+
review_params.permit(permitted_params)
|
84
|
+
end
|
85
|
+
|
86
|
+
def valid_rating?(rating)
|
87
|
+
["taste", "color", "texture", "smell"].include? rating
|
88
|
+
end
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
#### What's up with that?
|
93
|
+
- You have to do this for every action
|
94
|
+
- Controllers are obese, hard to parse and fragile
|
95
|
+
- Controllers are doing non-controller-y things
|
96
|
+
|
97
|
+
### Solution (With `Deserializer`)
|
98
|
+
`DishReviewDeserializer`:
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
module MyApi
|
102
|
+
module V1
|
103
|
+
class DishReviewDeserializer < Deserializer::Base
|
104
|
+
attributes :restaurant_id
|
105
|
+
:user_id
|
106
|
+
:description
|
107
|
+
|
108
|
+
attribute :name, key: :dish_name
|
109
|
+
|
110
|
+
has_one :ratings, :deserializer => RatingsDeserializer
|
111
|
+
|
112
|
+
def ratings
|
113
|
+
object
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
```
|
120
|
+
|
121
|
+
`RatingsDeserializer`:
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
module MyApi
|
125
|
+
module V1
|
126
|
+
class RatingsDeserializer < Deserializer::Base
|
127
|
+
|
128
|
+
attributes :taste,
|
129
|
+
:color,
|
130
|
+
:texture,
|
131
|
+
:smell
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
```
|
136
|
+
|
137
|
+
All of this allows your controller to be so very small:
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
class DishReviewsController < YourApiController::Base
|
141
|
+
def create
|
142
|
+
@review = DishReview.new( MyApi::V1::DishReviewDeserializer.from_params(params) )
|
143
|
+
|
144
|
+
if @review.save
|
145
|
+
# return review
|
146
|
+
else
|
147
|
+
# return sad errors splody
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# RUD
|
152
|
+
end
|
153
|
+
```
|
154
|
+
|
155
|
+
#### What's up with that?
|
156
|
+
- Un-pollutes controllers from all the parsing
|
157
|
+
- Builds deserializers that look like our serializers
|
158
|
+
|
159
|
+
## Definition
|
160
|
+
Inherit from `Deserializer::Base` and define it in much the same way you would an [ActiveModel::Serializer](https://github.com/rails-api/active_model_serializers).
|
161
|
+
|
162
|
+
### attributes
|
163
|
+
Use `attributes` for straight mapping from params to the model:
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
class PostDeserializer < Deserializer::Base
|
167
|
+
attributes :title,
|
168
|
+
:body
|
169
|
+
end
|
170
|
+
```
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
# Example params
|
174
|
+
{
|
175
|
+
"title" => "lorem",
|
176
|
+
"body" => "ipsum"
|
177
|
+
}
|
178
|
+
# Resulting hash
|
179
|
+
{
|
180
|
+
title: "lorem",
|
181
|
+
body: "ipsum"
|
182
|
+
}
|
183
|
+
```
|
184
|
+
|
185
|
+
### attribute
|
186
|
+
Allows the following customizations for each `attribute`
|
187
|
+
#### :key
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
class PostDeserializer < Deserializer::Base
|
191
|
+
attribute :title, ignore_empty: true
|
192
|
+
attribute :body, key: :content
|
193
|
+
end
|
194
|
+
```
|
195
|
+
|
196
|
+
`:content` here is what it will get in params while `:body` is what it will be inserted into the result.
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
# Example params
|
200
|
+
{
|
201
|
+
"title" => "lorem",
|
202
|
+
"content" => "ipsum"
|
203
|
+
}
|
204
|
+
# Resulting hash
|
205
|
+
{
|
206
|
+
title: "lorem",
|
207
|
+
body: "ipsum"
|
208
|
+
}
|
209
|
+
```
|
210
|
+
|
211
|
+
#### :ignore_empty
|
212
|
+
While `Deserializer`'s default is to pass all values through, this option will drop any key with `false`/`nil`/`""`/`[]`/`{}` values from the result.
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
# Example params
|
216
|
+
{
|
217
|
+
"title" => "",
|
218
|
+
"text" => nil
|
219
|
+
}
|
220
|
+
# Resulting hash
|
221
|
+
{}
|
222
|
+
```
|
223
|
+
|
224
|
+
#### :convert_with
|
225
|
+
Allows deserializing and converting a value at the same time. For example:
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
class Post < ActiveRecord::Base
|
229
|
+
belongs_to :post_type # this is a domain table
|
230
|
+
end
|
231
|
+
```
|
232
|
+
|
233
|
+
If we serialize with
|
234
|
+
|
235
|
+
```ruby
|
236
|
+
class PostSerializer < ActiveModel::Serializer
|
237
|
+
attribute :type
|
238
|
+
|
239
|
+
def type
|
240
|
+
object.post_type.symbolic_name
|
241
|
+
end
|
242
|
+
end
|
243
|
+
```
|
244
|
+
|
245
|
+
Then, when we get a symbolic name from the controller but want to work with an id in the backend, we can:
|
246
|
+
|
247
|
+
```ruby
|
248
|
+
class PostDeserializer < Deserializer::Base
|
249
|
+
attribute :title, ignore_empty: true
|
250
|
+
attribute :body
|
251
|
+
attribute :post_type_id, key: :type, convert_with: to_type_id
|
252
|
+
|
253
|
+
def to_type_id(value)
|
254
|
+
Type.find_by_symbolic_name.id
|
255
|
+
end
|
256
|
+
end
|
257
|
+
```
|
258
|
+
|
259
|
+
```ruby
|
260
|
+
# Example params
|
261
|
+
{
|
262
|
+
"title" => "lorem",
|
263
|
+
"body" => "ipsum",
|
264
|
+
"type" => "BLAGABLAG"
|
265
|
+
}
|
266
|
+
# Resulting hash
|
267
|
+
{
|
268
|
+
title: "lorem",
|
269
|
+
body: "ipsum",
|
270
|
+
post_type_id: 1
|
271
|
+
}
|
272
|
+
```
|
273
|
+
|
274
|
+
### has_one
|
275
|
+
`has_one` association expects a param and its deserializer:
|
276
|
+
|
277
|
+
```ruby
|
278
|
+
class DishDeserializer < Deserializer::Base
|
279
|
+
# probably other stuff
|
280
|
+
has_one :ratings, deserializer: RatingsDeserializer
|
281
|
+
end
|
282
|
+
|
283
|
+
class RatingsDeserializer < Deserializer::Base
|
284
|
+
attributes :taste,
|
285
|
+
:smell
|
286
|
+
end
|
287
|
+
```
|
288
|
+
|
289
|
+
```ruby
|
290
|
+
# Example params
|
291
|
+
{
|
292
|
+
"ratings" => {
|
293
|
+
"taste" => "bad",
|
294
|
+
"smell" => "good"
|
295
|
+
}
|
296
|
+
}
|
297
|
+
# Resulting hash
|
298
|
+
{
|
299
|
+
ratings: {
|
300
|
+
taste: "bad",
|
301
|
+
smell: "good"
|
302
|
+
}
|
303
|
+
}
|
304
|
+
```
|
305
|
+
|
306
|
+
#### Deserialize into a Different Name
|
307
|
+
In the example above, if `ratings` inside `Dish` is called `scores` in your ActiveRecord, you can:
|
308
|
+
|
309
|
+
```ruby
|
310
|
+
class DishDeserializer < Deserializer::Base
|
311
|
+
has_one :ratings, deserializer: RatingsDeserializer
|
312
|
+
|
313
|
+
def ratings
|
314
|
+
:scores
|
315
|
+
end
|
316
|
+
end
|
317
|
+
```
|
318
|
+
|
319
|
+
```ruby
|
320
|
+
# Example params
|
321
|
+
{
|
322
|
+
"ratings" => {
|
323
|
+
"taste" => "bad",
|
324
|
+
"smell" => "good"
|
325
|
+
}
|
326
|
+
}
|
327
|
+
# Resulting hash
|
328
|
+
{
|
329
|
+
scores: {
|
330
|
+
taste: "bad",
|
331
|
+
smell: "good"
|
332
|
+
}
|
333
|
+
}
|
334
|
+
```
|
335
|
+
|
336
|
+
#### Deserialize into Parent Object
|
337
|
+
To deserialize `ratings` into the `dish` object, you can use `object`:
|
338
|
+
|
339
|
+
```ruby
|
340
|
+
class DishDeserializer < Deserializer::Base
|
341
|
+
has_one :ratings, deserializer: RatingsDeserializer
|
342
|
+
|
343
|
+
def ratings
|
344
|
+
object
|
345
|
+
end
|
346
|
+
end
|
347
|
+
```
|
348
|
+
|
349
|
+
```ruby
|
350
|
+
# Resulting hash
|
351
|
+
{
|
352
|
+
taste: "bad",
|
353
|
+
smell: "good"
|
354
|
+
}
|
355
|
+
```
|
356
|
+
|
357
|
+
#### Deserialize into a Different Sub-object
|
358
|
+
|
359
|
+
```ruby
|
360
|
+
class DishDeserializer < Deserializer::Base
|
361
|
+
has_one :colors, deserializer: ColorsDeserializer
|
362
|
+
has_one :ratings, deserializer: RatingsDeserializer
|
363
|
+
|
364
|
+
def colors
|
365
|
+
:ratings
|
366
|
+
end
|
367
|
+
end
|
368
|
+
```
|
369
|
+
|
370
|
+
Given params:
|
371
|
+
|
372
|
+
```ruby
|
373
|
+
# Example params
|
374
|
+
{
|
375
|
+
"ratings" =>
|
376
|
+
{
|
377
|
+
"taste" => "bad",
|
378
|
+
"smell" => "good"
|
379
|
+
},
|
380
|
+
"colors" =>
|
381
|
+
{
|
382
|
+
"color" => "red"
|
383
|
+
}
|
384
|
+
}
|
385
|
+
# Resulting hash
|
386
|
+
{
|
387
|
+
ratings: {
|
388
|
+
taste: "bad",
|
389
|
+
smell: "good",
|
390
|
+
color: "red"
|
391
|
+
}
|
392
|
+
}
|
393
|
+
```
|
394
|
+
|
395
|
+
#### key
|
396
|
+
|
397
|
+
You can deserialize a `has_one` association into a different key from what the json gives you. For example:
|
398
|
+
```json
|
399
|
+
{
|
400
|
+
id: 6,
|
401
|
+
name: "mac & cheese",
|
402
|
+
alias:
|
403
|
+
{
|
404
|
+
id: 83,
|
405
|
+
name: "macaroni and cheese"
|
406
|
+
}
|
407
|
+
}
|
408
|
+
```
|
409
|
+
|
410
|
+
but your model is
|
411
|
+
|
412
|
+
```ruby
|
413
|
+
class Dish
|
414
|
+
has_one :alias
|
415
|
+
accepted_nested_attributes_for :alias
|
416
|
+
end
|
417
|
+
```
|
418
|
+
instead of renaming the hash in the controller, you can do
|
419
|
+
|
420
|
+
```ruby
|
421
|
+
class DishDeserializer < Deserializer::Base
|
422
|
+
attributes :id,
|
423
|
+
:name
|
424
|
+
|
425
|
+
has_one :alias_attributes, deserializer: AliasDeserializer, key: :alias
|
426
|
+
end
|
427
|
+
```
|
428
|
+
|
429
|
+
which would output
|
430
|
+
|
431
|
+
```ruby
|
432
|
+
{
|
433
|
+
id: 6,
|
434
|
+
name: "mac & cheese",
|
435
|
+
alias_attributes:
|
436
|
+
{
|
437
|
+
id: 83,
|
438
|
+
name: "macaroni and cheese"
|
439
|
+
}
|
440
|
+
}
|
441
|
+
```
|
442
|
+
|
443
|
+
|
444
|
+
### has_many
|
445
|
+
`has_many` association expects a param and its deserializer:
|
446
|
+
|
447
|
+
```ruby
|
448
|
+
class DishDeserializer < Deserializer::Base
|
449
|
+
# probably other stuff
|
450
|
+
has_many :ratings, deserializer: RatingsDeserializer
|
451
|
+
end
|
452
|
+
|
453
|
+
class RatingsDeserializer < Deserializer::Base
|
454
|
+
attributes :user_id,
|
455
|
+
:rating,
|
456
|
+
:comment
|
457
|
+
end
|
458
|
+
```
|
459
|
+
|
460
|
+
```ruby
|
461
|
+
# Example params
|
462
|
+
{
|
463
|
+
"ratings" => [
|
464
|
+
{ "user_id" => 6,
|
465
|
+
"rating" => 3,
|
466
|
+
"comment" => "not bad"
|
467
|
+
},
|
468
|
+
{ "user_id" => 25,
|
469
|
+
"rating" => 2,
|
470
|
+
"comment" => "gross"
|
471
|
+
}
|
472
|
+
]
|
473
|
+
}
|
474
|
+
# Resulting hash
|
475
|
+
{
|
476
|
+
ratings: [
|
477
|
+
{ user_id: 6,
|
478
|
+
rating: 3,
|
479
|
+
comment: "not bad"
|
480
|
+
},
|
481
|
+
{ user_id: 25,
|
482
|
+
rating: 2,
|
483
|
+
comment: "gross"
|
484
|
+
}
|
485
|
+
]
|
486
|
+
}
|
487
|
+
```
|
488
|
+
|
489
|
+
#### key
|
490
|
+
|
491
|
+
You can deserialize a `has_many` association into a different key from what the json gives you. For example:
|
492
|
+
```json
|
493
|
+
{
|
494
|
+
id: 6,
|
495
|
+
name: "mac & cheese",
|
496
|
+
aliases: [
|
497
|
+
{
|
498
|
+
id: 83,
|
499
|
+
name: "macaroni and cheese"
|
500
|
+
},
|
501
|
+
{
|
502
|
+
id: 86,
|
503
|
+
name: "cheesy pasta"
|
504
|
+
}
|
505
|
+
]
|
506
|
+
}
|
507
|
+
```
|
508
|
+
|
509
|
+
but your model is
|
510
|
+
|
511
|
+
```ruby
|
512
|
+
class Dish
|
513
|
+
has_many :aliases
|
514
|
+
accepted_nested_attributes_for :aliases
|
515
|
+
end
|
516
|
+
```
|
517
|
+
instead of renaming the hash in the controller, you can do
|
518
|
+
|
519
|
+
```ruby
|
520
|
+
class DishDeserializer < Deserializer::Base
|
521
|
+
attributes :id,
|
522
|
+
:name
|
523
|
+
|
524
|
+
has_many :aliases_attributes, deserializer: AliasDeserializer, key: :aliases
|
525
|
+
end
|
526
|
+
```
|
527
|
+
|
528
|
+
which would output
|
529
|
+
|
530
|
+
```ruby
|
531
|
+
{
|
532
|
+
id: 6,
|
533
|
+
name: "mac & cheese",
|
534
|
+
aliases_attributes: [
|
535
|
+
{
|
536
|
+
id: 83,
|
537
|
+
name: "macaroni and cheese"
|
538
|
+
},
|
539
|
+
{
|
540
|
+
id: 86,
|
541
|
+
name: "cheesy pasta"
|
542
|
+
}
|
543
|
+
]
|
544
|
+
}
|
545
|
+
```
|
546
|
+
|
547
|
+
### nests
|
548
|
+
Sometimes you get a flat param list, but want it to be nested for `updated_nested_attributes`
|
549
|
+
|
550
|
+
If you have 2 models that look like
|
551
|
+
|
552
|
+
```ruby
|
553
|
+
class RestaurantLocation
|
554
|
+
belongs_to :address
|
555
|
+
# t.string :name
|
556
|
+
end
|
557
|
+
|
558
|
+
# where Address is something like
|
559
|
+
t.string :line_1
|
560
|
+
t.string :line_2
|
561
|
+
t.string :city
|
562
|
+
t.string :state
|
563
|
+
```
|
564
|
+
|
565
|
+
And you want to update them at the same time, as they're closely tied, `nests` lets you define
|
566
|
+
|
567
|
+
```ruby
|
568
|
+
class ResaturantLocationDeserializer < Deserializer::Base
|
569
|
+
attribute :name
|
570
|
+
|
571
|
+
nests :address, deserializer: AddressDeserializer
|
572
|
+
end
|
573
|
+
|
574
|
+
class AddressDeserializer
|
575
|
+
attributes :line_1,
|
576
|
+
:line_2,
|
577
|
+
:city,
|
578
|
+
:state
|
579
|
+
end
|
580
|
+
```
|
581
|
+
And now you can take a single block of json
|
582
|
+
|
583
|
+
```ruby
|
584
|
+
# Example params into restaurant_location endpoint
|
585
|
+
{
|
586
|
+
"name" => "Little Caesars: Et Two Brute",
|
587
|
+
"line_1" => "2 Brute St.",
|
588
|
+
"city" => "Seattle",
|
589
|
+
"state" => "WA"
|
590
|
+
}
|
591
|
+
|
592
|
+
# Resulting hash
|
593
|
+
{
|
594
|
+
name: "Little Caesars: Et Two Brute",
|
595
|
+
address: {
|
596
|
+
line_1: "2 Brute St",
|
597
|
+
city: "Seattle",
|
598
|
+
state: "WA"
|
599
|
+
}
|
600
|
+
}
|
601
|
+
|
602
|
+
```
|
603
|
+
|
604
|
+
|
605
|
+
|
606
|
+
## Functions
|
607
|
+
### from_params
|
608
|
+
`MyDeserializer.from_params(params)` creates the JSON that your AR model will then consume.
|
609
|
+
|
610
|
+
```ruby
|
611
|
+
@review = DishReview.new( MyApi::V1::DishReviewDeserializer.from_params(params) )
|
612
|
+
```
|
613
|
+
|
614
|
+
### permitted_params
|
615
|
+
Just call `MyDeserializer.permitted_params` and you'll have the full array of keys you expect params to have.
|
616
|
+
|
617
|
+
## Installation
|
618
|
+
Add this line to your application's Gemfile:
|
619
|
+
|
620
|
+
```
|
621
|
+
gem 'deserializer'
|
622
|
+
```
|
623
|
+
|
624
|
+
And then execute:
|
625
|
+
|
626
|
+
```
|
627
|
+
$ bundle
|
628
|
+
```
|
629
|
+
|
630
|
+
Or install it yourself as:
|
631
|
+
|
632
|
+
```
|
633
|
+
$ gem install deserializer
|
634
|
+
```
|
635
|
+
|
636
|
+
## Contributing
|
637
|
+
1. Fork it ( [https://github.com/gaorlov/deserializer/fork](https://github.com/gaorlov/deserializer/fork) )
|
638
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
639
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
640
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
641
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'deserializer/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "iso-deserializer"
|
8
|
+
s.version = Deserializer::VERSION
|
9
|
+
s.authors = ["Isometric"]
|
10
|
+
s.email = ["andy@iso.io"]
|
11
|
+
s.homepage = "https://github.com/gaorlov/deserializer"
|
12
|
+
s.summary = "deserialization"
|
13
|
+
s.description = "conversion from complexy write params to a json blob that an AR model can consume"
|
14
|
+
s.license = "MIT"
|
15
|
+
|
16
|
+
s.files = `git ls-files -z`.split("\x0")
|
17
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
s.test_files = s.files.grep(%r{^(test|s|features)/})
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency "activesupport", ">= 5.0.0"
|
22
|
+
|
23
|
+
s.add_development_dependency "rake"
|
24
|
+
s.add_development_dependency "m", "~> 1.3.1"
|
25
|
+
end
|