deserializer 0.4.0 → 0.6.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 +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
|