deserializer 0.4.0 → 0.6.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 +10 -2
- data/README.md +104 -8
- data/deserializer.gemspec +1 -0
- data/lib/deserializer.rb +2 -1
- data/lib/deserializer/attributable.rb +54 -0
- data/lib/deserializer/attribute.rb +11 -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 +44 -0
- data/lib/deserializer/attribute/nested_association.rb +10 -0
- data/lib/deserializer/attribute/value_attribute.rb +33 -0
- data/lib/deserializer/base.rb +19 -94
- data/lib/deserializer/version.rb +1 -1
- data/test/lib/deserializers.rb +5 -0
- data/test/unit/deserializer_test.rb +48 -29
- metadata +25 -3
- data/lib/deserializer/associatable.rb +0 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8e98ac2dd5ac22cf71de5fe17aec446999b93dec
|
4
|
+
data.tar.gz: 423a1b3fcc3b5a8497c9aa14de5d570c969085ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a617f0e4c52e8397fd287f0d776db9ffbf57f094ab029747eb499a2062a8ebbbc92288fc4a01aba316d2fb86eb477af298afc4d361cf49f055641f7dd666208f
|
7
|
+
data.tar.gz: b24342df65559de3e0fa3b8f7dc9d48974e3403d560e6da805d18d88873e2b9ead8aeb17c8ffe34d44490960ce7ac9a3249a58889e0f619886b233d197b904c6
|
data/Gemfile.lock
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
deserializer (0.
|
4
|
+
deserializer (0.5.0)
|
5
5
|
activesupport
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
activesupport (4.2.
|
10
|
+
activesupport (4.2.4)
|
11
11
|
i18n (~> 0.7)
|
12
12
|
json (~> 1.7, >= 1.7.7)
|
13
13
|
minitest (~> 5.1)
|
@@ -16,6 +16,10 @@ GEM
|
|
16
16
|
docile (1.1.5)
|
17
17
|
i18n (0.7.0)
|
18
18
|
json (1.8.3)
|
19
|
+
m (1.3.4)
|
20
|
+
method_source (>= 0.6.7)
|
21
|
+
rake (>= 0.9.2.2)
|
22
|
+
method_source (0.8.2)
|
19
23
|
minitest (5.7.0)
|
20
24
|
multi_json (1.11.1)
|
21
25
|
rake (10.4.2)
|
@@ -34,6 +38,10 @@ PLATFORMS
|
|
34
38
|
DEPENDENCIES
|
35
39
|
bundler (~> 1.6)
|
36
40
|
deserializer!
|
41
|
+
m (~> 1.3.1)
|
37
42
|
minitest
|
38
43
|
rake
|
39
44
|
simplecov
|
45
|
+
|
46
|
+
BUNDLED WITH
|
47
|
+
1.11.2
|
data/README.md
CHANGED
@@ -29,8 +29,7 @@ But this goes into a flat DishReview model:
|
|
29
29
|
```ruby
|
30
30
|
t.belongs_to :restaurant
|
31
31
|
t.belongs_to :user
|
32
|
-
# field name different from API
|
33
|
-
t.string :name
|
32
|
+
t.string :name # field name different from API (dish_name)
|
34
33
|
t.string :description
|
35
34
|
t.string :taste
|
36
35
|
t.string :color
|
@@ -46,7 +45,7 @@ class DishReviewController < BaseController
|
|
46
45
|
|
47
46
|
def create
|
48
47
|
review_params = get_review_params(params)
|
49
|
-
@review =
|
48
|
+
@review = DishReview.new(review_params)
|
50
49
|
if @review.save
|
51
50
|
# return review
|
52
51
|
else
|
@@ -85,10 +84,7 @@ class DishReviewController < BaseController
|
|
85
84
|
end
|
86
85
|
|
87
86
|
def valid_rating?(rating)
|
88
|
-
|
89
|
-
|
90
|
-
@@ratings.include? rating
|
91
|
-
|
87
|
+
["taste", "color", "texture", "smell"].include? rating
|
92
88
|
end
|
93
89
|
end
|
94
90
|
```
|
@@ -397,7 +393,107 @@ Given params:
|
|
397
393
|
```
|
398
394
|
|
399
395
|
### has_many
|
400
|
-
|
396
|
+
`has_many` association expects a param and its deserializer:
|
397
|
+
|
398
|
+
```ruby
|
399
|
+
class DishDeserializer < Deserializer::Base
|
400
|
+
# probably other stuff
|
401
|
+
has_many :ratings, deserializer: RatingsDeserializer
|
402
|
+
end
|
403
|
+
|
404
|
+
class RatingsDeserializer < Deserializer::Base
|
405
|
+
attributes :user_id,
|
406
|
+
:rating,
|
407
|
+
:comment
|
408
|
+
end
|
409
|
+
```
|
410
|
+
|
411
|
+
```ruby
|
412
|
+
# Example params
|
413
|
+
{
|
414
|
+
"ratings" => [
|
415
|
+
{ "user_id" => 6,
|
416
|
+
"rating" => 3,
|
417
|
+
"comment" => "not bad"
|
418
|
+
},
|
419
|
+
{ "user_id" => 25,
|
420
|
+
"rating" => 2,
|
421
|
+
"comment" => "gross"
|
422
|
+
}
|
423
|
+
]
|
424
|
+
}
|
425
|
+
# Resulting hash
|
426
|
+
{
|
427
|
+
ratings: [
|
428
|
+
{ user_id: 6,
|
429
|
+
rating: 3,
|
430
|
+
comment: "not bad"
|
431
|
+
},
|
432
|
+
{ user_id: 25,
|
433
|
+
rating: 2,
|
434
|
+
comment: "gross"
|
435
|
+
}
|
436
|
+
]
|
437
|
+
}
|
438
|
+
```
|
439
|
+
|
440
|
+
#### key
|
441
|
+
|
442
|
+
You can deserialize a `has_many` association into a different key from what the json gives you. For example:
|
443
|
+
```json
|
444
|
+
{
|
445
|
+
id: 6,
|
446
|
+
name: "mac & cheese",
|
447
|
+
aliases: [
|
448
|
+
{
|
449
|
+
id: 83,
|
450
|
+
name: "macaroni and cheese"
|
451
|
+
},
|
452
|
+
{
|
453
|
+
id: 86,
|
454
|
+
name: "cheesy pasta"
|
455
|
+
}
|
456
|
+
]
|
457
|
+
}
|
458
|
+
```
|
459
|
+
|
460
|
+
but your model is
|
461
|
+
|
462
|
+
```ruby
|
463
|
+
class Dish
|
464
|
+
has_many :aliases
|
465
|
+
accepted_nested_attributes_for :aliases
|
466
|
+
end
|
467
|
+
```
|
468
|
+
instead of renaming the hash in the controller, you can do
|
469
|
+
|
470
|
+
```ruby
|
471
|
+
class DishDeserializer < Deserializer::Base
|
472
|
+
attributes :id,
|
473
|
+
:name
|
474
|
+
|
475
|
+
has_many :aliases_attributes, deserializer: AliasDeserializer, key: :aliases
|
476
|
+
end
|
477
|
+
```
|
478
|
+
|
479
|
+
which would output
|
480
|
+
|
481
|
+
```ruby
|
482
|
+
{
|
483
|
+
id: 6,
|
484
|
+
name: "mac & cheese",
|
485
|
+
aliases_attributes: [
|
486
|
+
{
|
487
|
+
id: 83,
|
488
|
+
name: "macaroni and cheese"
|
489
|
+
},
|
490
|
+
{
|
491
|
+
id: 86,
|
492
|
+
name: "cheesy pasta"
|
493
|
+
}
|
494
|
+
]
|
495
|
+
}
|
496
|
+
```
|
401
497
|
|
402
498
|
### nests
|
403
499
|
Sometimes you get a flat param list, but want it to be nested for `updated_nested_attributes`
|
data/deserializer.gemspec
CHANGED
data/lib/deserializer.rb
CHANGED
@@ -3,7 +3,8 @@ require 'active_support'
|
|
3
3
|
require 'active_support/concern'
|
4
4
|
|
5
5
|
module Deserializer
|
6
|
-
autoload :
|
6
|
+
autoload :Attribute, 'deserializer/attribute'
|
7
|
+
autoload :Attributable, 'deserializer/attributable'
|
7
8
|
autoload :Base, 'deserializer/base'
|
8
9
|
autoload :DeserializerError, 'deserializer/deserializer_error'
|
9
10
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Deserializer
|
2
|
+
module Attributable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
class << self
|
7
|
+
# deserializer interface functions
|
8
|
+
|
9
|
+
def attributes( *attrs )
|
10
|
+
self.__attrs ||= []
|
11
|
+
attrs.each do |attr|
|
12
|
+
__attrs << Attribute::Attribute.new( Attribute::ValueAttribute, attr, {} )
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def attribute( name, opts = {} )
|
17
|
+
self.__attrs ||= []
|
18
|
+
__attrs << Attribute::Attribute.new( Attribute::ValueAttribute, name, opts )
|
19
|
+
end
|
20
|
+
|
21
|
+
def has_one( name, opts = {} )
|
22
|
+
unless opts[:deserializer]
|
23
|
+
raise DeserializerError, class: self, message: "has_one associations need a deserilaizer"
|
24
|
+
end
|
25
|
+
|
26
|
+
self.__attrs ||= []
|
27
|
+
__attrs << Attribute::Attribute.new( Attribute::HasOneAssociation, name, opts )
|
28
|
+
end
|
29
|
+
|
30
|
+
def has_many( name, opts = {} )
|
31
|
+
unless opts[:deserializer]
|
32
|
+
raise DeserializerError, class: self, message: "has_many associations need a deserilaizer"
|
33
|
+
end
|
34
|
+
|
35
|
+
self.__attrs ||= []
|
36
|
+
__attrs << Attribute::Attribute.new( Attribute::HasManyAssociation, name, opts )
|
37
|
+
end
|
38
|
+
|
39
|
+
def belongs_to( *args )
|
40
|
+
raise DeserializerError, class: self, message: "belongs_to is unsupported."
|
41
|
+
end
|
42
|
+
|
43
|
+
def nests( name, opts = {} )
|
44
|
+
unless opts[:deserializer]
|
45
|
+
raise DeserializerError, class: self, message: "nested associations need a deserilaizer"
|
46
|
+
end
|
47
|
+
|
48
|
+
self.__attrs ||= []
|
49
|
+
__attrs << Attribute::Attribute.new( Attribute::NestedAssociation, name, opts )
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Deserializer
|
2
|
+
module Attribute
|
3
|
+
autoload :Base, "deserializer/attribute/base"
|
4
|
+
autoload :Association, "deserializer/attribute/association"
|
5
|
+
autoload :Attribute, "deserializer/attribute/attribute"
|
6
|
+
autoload :HasManyAssociation, "deserializer/attribute/has_many_association"
|
7
|
+
autoload :HasOneAssociation, "deserializer/attribute/has_one_association"
|
8
|
+
autoload :NestedAssociation, "deserializer/attribute/nested_association"
|
9
|
+
autoload :ValueAttribute, "deserializer/attribute/value_attribute"
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Deserializer
|
2
|
+
module Attribute
|
3
|
+
class Attribute
|
4
|
+
def initialize( type, name, opts )
|
5
|
+
@type = type
|
6
|
+
@name = name
|
7
|
+
@opts = opts
|
8
|
+
end
|
9
|
+
|
10
|
+
def key
|
11
|
+
@opts.fetch :key, @name
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_hash( params, object )
|
15
|
+
attribute = @type.new( @name, @opts, object )
|
16
|
+
attribute.to_hash( params )
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Deserializer
|
2
|
+
module Attribute
|
3
|
+
class Base
|
4
|
+
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
def initialize( name, opts = {}, object )
|
8
|
+
self.name = name
|
9
|
+
self.opts = opts
|
10
|
+
self.object = object
|
11
|
+
end
|
12
|
+
|
13
|
+
# simple object
|
14
|
+
# { key => value }
|
15
|
+
|
16
|
+
# has_* object
|
17
|
+
# { key => { deserialized obejct }}
|
18
|
+
|
19
|
+
# has_one :whatever; where def wahtever{ object }
|
20
|
+
# { object }
|
21
|
+
def to_hash( params )
|
22
|
+
return {} unless params.has_key? key
|
23
|
+
tuple( params )
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_accessor :opts, :value, :object
|
29
|
+
attr_writer :name
|
30
|
+
|
31
|
+
def key
|
32
|
+
@key ||= opts.fetch :key, name
|
33
|
+
end
|
34
|
+
|
35
|
+
def tuple( params = {} )
|
36
|
+
value = value( params )
|
37
|
+
if value == :ignore
|
38
|
+
{}
|
39
|
+
else
|
40
|
+
{ name => value }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def value( params = {} )
|
45
|
+
return "not implemented"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Deserializer
|
2
|
+
module Attribute
|
3
|
+
class HasManyAssociation < Association
|
4
|
+
|
5
|
+
def value( params )
|
6
|
+
target = []
|
7
|
+
params[key].each do |association_datum|
|
8
|
+
target << deserializer.from_params( association_datum )
|
9
|
+
end
|
10
|
+
target
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Deserializer
|
2
|
+
module Attribute
|
3
|
+
class HasOneAssociation < Association
|
4
|
+
|
5
|
+
def to_hash( params )
|
6
|
+
return {} unless params[name]
|
7
|
+
value = deserializer.from_params( params[key] )
|
8
|
+
|
9
|
+
if object.respond_to? name
|
10
|
+
|
11
|
+
target = object.send( name )
|
12
|
+
|
13
|
+
# has_one :thing, deserializer: ThingDeserializer
|
14
|
+
#
|
15
|
+
# def thing
|
16
|
+
# object
|
17
|
+
# end
|
18
|
+
if target == object.object
|
19
|
+
return value
|
20
|
+
|
21
|
+
# has_one :thing, deserializer: ThingDeserializer
|
22
|
+
# has_one :gniht, deserializer: GnihtDeserializer
|
23
|
+
#
|
24
|
+
# def thing
|
25
|
+
# object[:gniht]
|
26
|
+
# end
|
27
|
+
elsif target.is_a? Hash
|
28
|
+
return target.merge value
|
29
|
+
|
30
|
+
# has_one :thing, deserializer: GnihtDeserializer
|
31
|
+
#
|
32
|
+
# def thing
|
33
|
+
# :some_other_key
|
34
|
+
# end
|
35
|
+
else
|
36
|
+
return { target => value }
|
37
|
+
end
|
38
|
+
else
|
39
|
+
return { key => value }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Deserializer
|
2
|
+
module Attribute
|
3
|
+
class ValueAttribute < Base
|
4
|
+
|
5
|
+
def value( params )
|
6
|
+
value = params[key]
|
7
|
+
|
8
|
+
if opts[:ignore_empty] && empty?(value)
|
9
|
+
return :ignore
|
10
|
+
end
|
11
|
+
|
12
|
+
if opts[:convert_with]
|
13
|
+
method = opts[:convert_with]
|
14
|
+
if object.respond_to? method
|
15
|
+
return object.send method, value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
# other options go here
|
19
|
+
|
20
|
+
value
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def empty?(value)
|
26
|
+
!value ||
|
27
|
+
value == "" ||
|
28
|
+
value == {} ||
|
29
|
+
value == []
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/deserializer/base.rb
CHANGED
@@ -1,61 +1,40 @@
|
|
1
1
|
module Deserializer
|
2
2
|
class Base
|
3
3
|
|
4
|
-
## has_one, nested, etc associations
|
5
|
-
include Deserializer::
|
4
|
+
## atribute, has_one, nested, etc associations
|
5
|
+
include Deserializer::Attributable
|
6
6
|
|
7
7
|
class << self
|
8
|
-
attr_accessor :
|
9
|
-
|
10
|
-
# deserializer interface functions
|
11
|
-
|
12
|
-
def attributes(*attrs)
|
13
|
-
self.attrs ||= {}
|
14
|
-
attrs.each do |attr|
|
15
|
-
self.attrs[attr] = {attr: attr, options: {}}
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def attribute(attr, options = {})
|
20
|
-
self.attrs ||= {}
|
21
|
-
key = options.fetch(:key, attr)
|
22
|
-
self.attrs[key] = {attr: attr, options: options}
|
23
|
-
end
|
8
|
+
attr_accessor :__attrs
|
24
9
|
|
25
10
|
# deserializer usage functions
|
26
11
|
|
27
12
|
def from_params( params = {} )
|
28
|
-
self.new(
|
13
|
+
self.new( params ).deserialize
|
29
14
|
end
|
30
15
|
|
31
16
|
def permitted_params
|
32
|
-
self.
|
17
|
+
self.__attrs.map(&:key)
|
33
18
|
end
|
34
|
-
|
35
19
|
end
|
36
20
|
|
37
21
|
attr_reader :object
|
38
22
|
|
39
23
|
def deserialize
|
40
|
-
self.class.attrs.each do |param_key, object_key|
|
41
|
-
# don't bother with keys that aren't in params
|
42
|
-
next unless params.has_key? param_key
|
43
24
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
25
|
+
object ||= {}
|
26
|
+
|
27
|
+
# deserialize
|
28
|
+
self.class.__attrs.each do |attr|
|
29
|
+
object.merge!( attr.to_hash( params, self ) ) do |key, old_value, new_value|
|
30
|
+
# in the case that 2 has_ones merge into the same key. Not sure i want to support this
|
31
|
+
if old_value.is_a?( Hash ) && new_value.is_a?( Hash )
|
32
|
+
old_value.merge new_value
|
33
|
+
else
|
34
|
+
new_value
|
35
|
+
end
|
52
36
|
end
|
53
37
|
end
|
54
|
-
|
55
|
-
self.class.nested_attrs ||= {}
|
56
|
-
self.class.nested_attrs.each do |target, options|
|
57
|
-
deserialize_nested target, options[:deserializer]
|
58
|
-
end
|
59
38
|
object
|
60
39
|
end
|
61
40
|
|
@@ -64,67 +43,13 @@ module Deserializer
|
|
64
43
|
attr_accessor :params
|
65
44
|
attr_writer :object
|
66
45
|
|
67
|
-
def initialize(
|
46
|
+
def initialize( params = {})
|
68
47
|
unless params
|
69
48
|
raise DeserializerError, class: self.class, message: "params cannot be nil"
|
70
49
|
end
|
71
50
|
|
72
51
|
self.params = params
|
73
|
-
self.object =
|
74
|
-
end
|
75
|
-
|
76
|
-
def deseralize_association(association, deserializer)
|
77
|
-
# check for method defining the target object (something, in the example below)
|
78
|
-
#
|
79
|
-
# class ExampleDeserializer < Deserializer::Base
|
80
|
-
# has_one :something, deserializer: SomethingDeserializer
|
81
|
-
#
|
82
|
-
# def something
|
83
|
-
# object
|
84
|
-
# end
|
85
|
-
# end
|
86
|
-
|
87
|
-
if self.respond_to? association
|
88
|
-
|
89
|
-
target = self.send( association )
|
90
|
-
|
91
|
-
unless target.is_a? Hash
|
92
|
-
target = object[target] ||= {}
|
93
|
-
end
|
94
|
-
else
|
95
|
-
target = object[association] ||= {}
|
96
|
-
end
|
97
|
-
|
98
|
-
deserializer.new( target, params[association] ).deserialize
|
99
|
-
end
|
100
|
-
|
101
|
-
def deserialize_nested( target, deserializer )
|
102
|
-
target = object[target] ||= {}
|
103
|
-
deserializer.new( target, params ).deserialize
|
104
|
-
end
|
105
|
-
|
106
|
-
def assign_value( attribute, value, options = {} )
|
107
|
-
if options[:ignore_empty] && empty?(value)
|
108
|
-
return
|
109
|
-
end
|
110
|
-
if options[:convert_with]
|
111
|
-
method = options[:convert_with]
|
112
|
-
if self.respond_to? method
|
113
|
-
self.object[attribute] = self.send method, value
|
114
|
-
return
|
115
|
-
end
|
116
|
-
end
|
117
|
-
# other options go here
|
118
|
-
|
119
|
-
self.object[attribute] = value
|
120
|
-
|
121
|
-
end
|
122
|
-
|
123
|
-
def empty?(value)
|
124
|
-
!value ||
|
125
|
-
value == "" ||
|
126
|
-
value == {} ||
|
127
|
-
value == []
|
52
|
+
self.object = {}
|
128
53
|
end
|
129
54
|
end
|
130
|
-
end
|
55
|
+
end
|
data/lib/deserializer/version.rb
CHANGED
data/test/lib/deserializers.rb
CHANGED
@@ -122,4 +122,9 @@ class NestableDeserializer < Deserializer::Base
|
|
122
122
|
:attr_1
|
123
123
|
|
124
124
|
nests :nested_object, deserializer: ::NestedDeserializer
|
125
|
+
end
|
126
|
+
|
127
|
+
class HasManyDeserializer < Deserializer::Base
|
128
|
+
attribute :id
|
129
|
+
has_many :attributes, deserializer: AttributeDeserializer
|
125
130
|
end
|
@@ -20,10 +20,6 @@ class DeserializerTest < Minitest::Test
|
|
20
20
|
assert_equal ({user_id: 6, text: "text"}) , BasicDeserializer.from_params( @params )
|
21
21
|
end
|
22
22
|
|
23
|
-
def test_permitted_params
|
24
|
-
assert_equal [:user_id, :text] , BasicDeserializer.permitted_params
|
25
|
-
end
|
26
|
-
|
27
23
|
def test_does_not_eat_false_or_nil_values
|
28
24
|
params = { user_id: nil,
|
29
25
|
text: false,
|
@@ -32,6 +28,10 @@ class DeserializerTest < Minitest::Test
|
|
32
28
|
assert_equal ({user_id: nil, text: false}) , BasicDeserializer.from_params( params )
|
33
29
|
end
|
34
30
|
|
31
|
+
def test_permitted_params
|
32
|
+
assert_equal [:user_id, :text] , BasicDeserializer.permitted_params
|
33
|
+
end
|
34
|
+
|
35
35
|
def test_permitted_params_with_attr_key
|
36
36
|
assert_equal [:user, :text] , AttributeDeserializer.permitted_params
|
37
37
|
end
|
@@ -72,6 +72,27 @@ class DeserializerTest < Minitest::Test
|
|
72
72
|
assert_equal nil, AttributeDeserializer.from_params( @params )[:i_shouldnt_be_here]
|
73
73
|
end
|
74
74
|
|
75
|
+
def test_supports_conversions
|
76
|
+
expected = { real_range: (1..4), bad_range: (1..1)}
|
77
|
+
params = { real_range: [1, 12, 4], bad_range: 1}
|
78
|
+
|
79
|
+
assert_equal expected, ConversionDeserializer.from_params( params )
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_supports_conversions_with_key
|
83
|
+
expected = { real_range: (1..4), bad_range: (1..1)}
|
84
|
+
params = { real: [1, 4], bad: 1}
|
85
|
+
|
86
|
+
assert_equal expected, KeyedConversionDeserializer.from_params( params )
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_supports_conversions_with_ignore_empty
|
90
|
+
expected = { real_range: (1..4)}
|
91
|
+
params = { real: [1, 4], bad: nil}
|
92
|
+
|
93
|
+
assert_equal expected, NillableConversionDeserializer.from_params( params )
|
94
|
+
end
|
95
|
+
|
75
96
|
def test_has_one
|
76
97
|
expected = { internal: :thing, params: { user_id: 6, text: "text" }}
|
77
98
|
params = { external: :thing, params: @params }
|
@@ -110,49 +131,47 @@ class DeserializerTest < Minitest::Test
|
|
110
131
|
assert_equal expected, HasOneWithObjectTargetDeserializer.from_params( params )
|
111
132
|
end
|
112
133
|
|
113
|
-
def
|
134
|
+
def test_belongs_to_unpermitted
|
114
135
|
assert_raises Deserializer::DeserializerError do
|
115
|
-
BasicDeserializer.
|
136
|
+
BasicDeserializer.belongs_to :explody
|
116
137
|
end
|
117
138
|
end
|
118
139
|
|
119
|
-
def
|
140
|
+
def test_tests_requires_deserializer
|
120
141
|
assert_raises Deserializer::DeserializerError do
|
121
|
-
BasicDeserializer.
|
142
|
+
BasicDeserializer.nests :splosion
|
122
143
|
end
|
123
144
|
end
|
124
145
|
|
125
|
-
def
|
126
|
-
|
127
|
-
|
146
|
+
def test_supports_nested
|
147
|
+
params = { id: 1, attr_1: "blah", attr_2: "something" }
|
148
|
+
expected = { id: 1, attr_1: "blah", nested_object: { name: "blah", attr_2: "something" } }
|
128
149
|
|
129
|
-
assert_equal expected,
|
150
|
+
assert_equal expected, NestableDeserializer.from_params( params )
|
130
151
|
end
|
131
152
|
|
132
|
-
def
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
assert_equal expected, KeyedConversionDeserializer.from_params( params )
|
153
|
+
def test_has_many_requires_deserializer
|
154
|
+
assert_raises Deserializer::DeserializerError do
|
155
|
+
BasicDeserializer.has_many :splosions
|
156
|
+
end
|
137
157
|
end
|
138
158
|
|
139
|
-
def
|
140
|
-
|
141
|
-
|
159
|
+
def test_supports_has_many
|
160
|
+
params = { id: 1, attributes: [{user: 6, text: "lol"}, {user: 6, text: "something"}] }
|
161
|
+
expected = { id: 1, attributes: [{user_id: 6, text: "lol"}, {user_id: 6, text: "something"}] }
|
142
162
|
|
143
|
-
assert_equal expected,
|
163
|
+
assert_equal expected, HasManyDeserializer.from_params( params )
|
144
164
|
end
|
145
165
|
|
146
|
-
def
|
147
|
-
|
148
|
-
BasicDeserializer.nests :splosion
|
149
|
-
end
|
166
|
+
def test_has_many_handles_no_input
|
167
|
+
assert_equal ({}), HasManyDeserializer.from_params( {} )
|
150
168
|
end
|
151
169
|
|
152
|
-
def
|
153
|
-
|
154
|
-
|
170
|
+
def test_has_one_handles_no_input
|
171
|
+
assert_equal ({}), VanillaHasOneDeserializer.from_params( {} )
|
172
|
+
end
|
155
173
|
|
156
|
-
|
174
|
+
def test_nested_handles_no_input
|
175
|
+
assert_equal ({nested_object: {}}), NestableDeserializer.from_params( {} )
|
157
176
|
end
|
158
177
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deserializer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Greg Orlov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: m
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.3.1
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.3.1
|
55
69
|
description: conversion from complexy write params to a json blob that an AR model
|
56
70
|
can consume
|
57
71
|
email:
|
@@ -68,7 +82,15 @@ files:
|
|
68
82
|
- Rakefile
|
69
83
|
- deserializer.gemspec
|
70
84
|
- lib/deserializer.rb
|
71
|
-
- lib/deserializer/
|
85
|
+
- lib/deserializer/attributable.rb
|
86
|
+
- lib/deserializer/attribute.rb
|
87
|
+
- lib/deserializer/attribute/association.rb
|
88
|
+
- lib/deserializer/attribute/attribute.rb
|
89
|
+
- lib/deserializer/attribute/base.rb
|
90
|
+
- lib/deserializer/attribute/has_many_association.rb
|
91
|
+
- lib/deserializer/attribute/has_one_association.rb
|
92
|
+
- lib/deserializer/attribute/nested_association.rb
|
93
|
+
- lib/deserializer/attribute/value_attribute.rb
|
72
94
|
- lib/deserializer/base.rb
|
73
95
|
- lib/deserializer/deserializer_error.rb
|
74
96
|
- lib/deserializer/version.rb
|
@@ -1,38 +0,0 @@
|
|
1
|
-
module Deserializer
|
2
|
-
module Associatable
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
included do
|
6
|
-
class << self
|
7
|
-
def has_one( target, opts = {})
|
8
|
-
deserializer = opts[:deserializer]
|
9
|
-
|
10
|
-
unless deserializer
|
11
|
-
raise DeserializerError, class: self, message: "has_one associations need a deserilaizer"
|
12
|
-
end
|
13
|
-
|
14
|
-
self.attrs[target] = { attr: nil, deserializer: deserializer }
|
15
|
-
end
|
16
|
-
|
17
|
-
def has_many(*args)
|
18
|
-
raise DeserializerError, class: self, message: "has_many is intentionally unsupported."
|
19
|
-
end
|
20
|
-
|
21
|
-
def belongs_to(*args)
|
22
|
-
raise DeserializerError, class: self, message: "belongs_to is unsupported."
|
23
|
-
end
|
24
|
-
|
25
|
-
def nests(target, opts = {})
|
26
|
-
deserializer = opts[:deserializer]
|
27
|
-
|
28
|
-
unless deserializer
|
29
|
-
raise DeserializerError, class: self, message: "nested associations need a deserilaizer"
|
30
|
-
end
|
31
|
-
|
32
|
-
self.nested_attrs ||= {}
|
33
|
-
self.nested_attrs[target] = { deserializer: deserializer }
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|