representable 2.1.0 → 2.1.1
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/CHANGES.md +25 -0
- data/lib/representable.rb +2 -0
- data/lib/representable/apply.rb +13 -0
- data/lib/representable/binding.rb +1 -1
- data/lib/representable/config.rb +5 -1
- data/lib/representable/debug.rb +95 -0
- data/lib/representable/definition.rb +6 -0
- data/lib/representable/deserializer.rb +5 -1
- data/lib/representable/populator.rb +10 -2
- data/lib/representable/serializer.rb +5 -1
- data/lib/representable/version.rb +1 -1
- data/test/config_test.rb +25 -9
- data/test/definition_test.rb +10 -0
- data/test/schema_test.rb +35 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4c1cc5843478c8c3c889dabd023eca71e622da8
|
4
|
+
data.tar.gz: c8b2850a2418de5d94dbc1024f5d84c93a979976
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8447a73176a4dfd5cc11d7767721e083757e2c9eeeb9e0bde32d73b17fea141fd6954ca05ce45f9e88c8393d9341981cce7b4e5fc4836f7eaed39d05a0890bc8
|
7
|
+
data.tar.gz: a4175164b4f3eb64db40630b7d9fcc4e1574cc075268f87e6cdafbe2a8648861a07f0302fbbc54431ac6bb5934b4c3f12e704a3459a4b3c134acf029ff794496
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,28 @@
|
|
1
|
+
# 2.1.1
|
2
|
+
|
3
|
+
* Added `Definition#delete!` to remove options.
|
4
|
+
* Added `Representable::apply` do iterate and change schemas.
|
5
|
+
* Added `Config.remove` to remove properties.
|
6
|
+
* Added `Representable::Debug` which just has to be included into your represented object.
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
song.extend(SongRepresenter).extend(Representable::Debug).from_json("..")
|
10
|
+
song.extend(SongRepresenter).extend(Representable::Debug).to_json("..")
|
11
|
+
```
|
12
|
+
|
13
|
+
It can also be included statically into your representer or decorator.
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
class SongRepresenter < Representable::Decorator
|
17
|
+
include Representable::JSON
|
18
|
+
include Representable::Debug
|
19
|
+
|
20
|
+
property :title
|
21
|
+
end
|
22
|
+
```
|
23
|
+
|
24
|
+
It is great.
|
25
|
+
|
1
26
|
# 2.1.0
|
2
27
|
|
3
28
|
## Breaking Changes
|
data/lib/representable.rb
CHANGED
@@ -7,6 +7,7 @@ require 'representable/mapper'
|
|
7
7
|
require 'representable/for_collection'
|
8
8
|
require 'representable/represent'
|
9
9
|
require 'representable/declarative'
|
10
|
+
require 'representable/apply'
|
10
11
|
|
11
12
|
|
12
13
|
require 'uber/callable'
|
@@ -23,6 +24,7 @@ module Representable
|
|
23
24
|
extend Feature
|
24
25
|
extend ForCollection
|
25
26
|
extend Represent
|
27
|
+
extend Apply
|
26
28
|
# register_feature Representable # Representable gets included automatically when creating inline representer.
|
27
29
|
end
|
28
30
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Representable
|
2
|
+
module Apply
|
3
|
+
# Iterates over all property/collection definitions and yields the Definition instance.
|
4
|
+
def apply(&block)
|
5
|
+
representable_attrs.each do |dfn|
|
6
|
+
block.call(dfn)
|
7
|
+
dfn.representer_module.extend(Apply).apply(&block) if dfn.representer_module # nested.
|
8
|
+
end
|
9
|
+
|
10
|
+
self
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/representable/config.rb
CHANGED
@@ -39,6 +39,10 @@ module Representable
|
|
39
39
|
self[name.to_s]
|
40
40
|
end
|
41
41
|
|
42
|
+
def remove(name)
|
43
|
+
delete(name.to_s)
|
44
|
+
end
|
45
|
+
|
42
46
|
extend Forwardable
|
43
47
|
def_delegators :values, :each # so we look like an array. this is only used in Mapper. we could change that so we don't need to hide the hash.
|
44
48
|
|
@@ -63,7 +67,7 @@ module Representable
|
|
63
67
|
|
64
68
|
# delegate #collect etc to Definitions instance.
|
65
69
|
extend Forwardable
|
66
|
-
def_delegators :@definitions, :get, :add, :each, :size
|
70
|
+
def_delegators :@definitions, :get, :add, :each, :size, :remove
|
67
71
|
# #collect comes from Hash and then gets delegated to @definitions. don't like that.
|
68
72
|
|
69
73
|
def wrap=(value)
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Representable
|
2
|
+
module Debug
|
3
|
+
def self.extended(represented)
|
4
|
+
represented.extend Representable
|
5
|
+
end
|
6
|
+
|
7
|
+
module Representable
|
8
|
+
def update_properties_from(doc, options, format)
|
9
|
+
puts
|
10
|
+
puts "[Deserialize]........."
|
11
|
+
puts "[Deserialize] document #{doc.inspect}"
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_representation_with(doc, options, format)
|
16
|
+
puts
|
17
|
+
puts "[Serialize]........."
|
18
|
+
puts "[Serialize]"
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def representable_mapper(*args)
|
23
|
+
super.extend(Mapper)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module Binding
|
28
|
+
def read(doc)
|
29
|
+
value = super
|
30
|
+
puts " #read --> #{value.inspect}"
|
31
|
+
value
|
32
|
+
end
|
33
|
+
|
34
|
+
def evaluate_option(name, *args, &block)
|
35
|
+
puts "=====#{self[name]}" if name ==:prepare
|
36
|
+
puts (evaled = self[name]) ?
|
37
|
+
" #evaluate_option [#{name}]: eval!!!" :
|
38
|
+
" #evaluate_option [#{name}]: skipping"
|
39
|
+
value = super
|
40
|
+
puts " #evaluate_option [#{name}]: --> #{value}" if evaled
|
41
|
+
puts " #evaluate_option [#{name}]: -->= #{args.first}" if name == :setter
|
42
|
+
value
|
43
|
+
end
|
44
|
+
|
45
|
+
def populator
|
46
|
+
super.extend(Populator)
|
47
|
+
end
|
48
|
+
|
49
|
+
def serializer
|
50
|
+
super.extend(Serializer)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
module Populator
|
55
|
+
def deserialize(fragment)
|
56
|
+
puts " Populator#deserialize: #{fragment.inspect}"
|
57
|
+
puts " : typed? is false, skipping Deserializer." if ! @binding.typed?
|
58
|
+
super
|
59
|
+
end
|
60
|
+
|
61
|
+
def deserializer
|
62
|
+
super.extend(Deserializer)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
module Deserializer
|
67
|
+
def create_object(fragment, *args)
|
68
|
+
value = super
|
69
|
+
puts " Deserializer#create_object: --> #{value.inspect}"
|
70
|
+
value
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
module Serializer
|
75
|
+
def marshal(object, user_options)
|
76
|
+
puts " Serializer#marshal: --> #{object.inspect}"
|
77
|
+
super
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
module Mapper
|
82
|
+
def uncompile_fragment(bin, doc)
|
83
|
+
bin.extend(Binding)
|
84
|
+
puts " uncompile_fragment: #{bin.name}"
|
85
|
+
super
|
86
|
+
end
|
87
|
+
|
88
|
+
def compile_fragment(bin, doc)
|
89
|
+
bin.extend(Binding)
|
90
|
+
puts " compile_fragment: #{bin.name}"
|
91
|
+
super
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -28,10 +28,14 @@ module Representable
|
|
28
28
|
return object unless @binding.representable?
|
29
29
|
|
30
30
|
@binding.evaluate_option(:deserialize, object, fragment) do
|
31
|
-
object
|
31
|
+
demarshal(object, fragment, options)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
def demarshal(object, fragment, options)
|
36
|
+
object.send(@binding.deserialize_method, fragment, options)
|
37
|
+
end
|
38
|
+
|
35
39
|
def prepare(object)
|
36
40
|
@binding.evaluate_option(:prepare, object) do
|
37
41
|
prepare!(object)
|
@@ -31,13 +31,17 @@ module Representable
|
|
31
31
|
return yield if @binding.evaluate_option(:skip_parse, fragment) # TODO: move this into Deserializer.
|
32
32
|
|
33
33
|
# use a Deserializer to transform fragment to/into object.
|
34
|
-
|
34
|
+
deserializer.call(fragment) # CollectionDeserializer/HashDeserializer/etc.
|
35
35
|
end
|
36
36
|
|
37
37
|
def deserializer_class
|
38
38
|
Deserializer
|
39
39
|
end
|
40
40
|
|
41
|
+
def deserializer
|
42
|
+
deserializer_class.new(@binding)
|
43
|
+
end
|
44
|
+
|
41
45
|
|
42
46
|
# A separated collection deserializer/populator allows us better dealing with populating/modifying
|
43
47
|
# collections of models. (e.g. replace, update, push, etc.).
|
@@ -45,7 +49,11 @@ module Representable
|
|
45
49
|
class Collection < self
|
46
50
|
private
|
47
51
|
def deserialize(fragment)
|
48
|
-
return
|
52
|
+
return deserializer.call(fragment)
|
53
|
+
end
|
54
|
+
|
55
|
+
def deserializer
|
56
|
+
Deserializer::Collection.new(@binding)
|
49
57
|
end
|
50
58
|
end
|
51
59
|
|
@@ -16,10 +16,14 @@ module Representable
|
|
16
16
|
return object unless @binding.representable?
|
17
17
|
|
18
18
|
@binding.evaluate_option(:serialize, object) do
|
19
|
-
object
|
19
|
+
marshal(object, user_options)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
def marshal(object, user_options)
|
24
|
+
object.send(@binding.serialize_method, user_options.merge!({:wrap => false}))
|
25
|
+
end
|
26
|
+
|
23
27
|
|
24
28
|
class Collection < self
|
25
29
|
def serialize(array, *args)
|
data/test/config_test.rb
CHANGED
@@ -39,6 +39,16 @@ class ConfigTest < MiniTest::Spec
|
|
39
39
|
# forwarded to Config#definitions
|
40
40
|
# that goes to ConfigDefinitionsTest
|
41
41
|
describe "#add" do
|
42
|
+
describe "returns" do
|
43
|
+
it do
|
44
|
+
# #add returns Definition.`
|
45
|
+
subject = Representable::Config.new.add(:title, {:me => true})
|
46
|
+
|
47
|
+
subject.must_be_kind_of Representable::Definition
|
48
|
+
subject[:me].must_equal true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
42
52
|
before { subject.add(:title, {:me => true}) }
|
43
53
|
|
44
54
|
# must be kind of Definition
|
@@ -65,6 +75,20 @@ class ConfigTest < MiniTest::Spec
|
|
65
75
|
end
|
66
76
|
|
67
77
|
|
78
|
+
describe "#remove" do
|
79
|
+
subject { Representable::Config.new }
|
80
|
+
|
81
|
+
it do
|
82
|
+
subject.add(:title, {:me => true})
|
83
|
+
subject.add(:genre, {})
|
84
|
+
subject.get(:genre).must_be_kind_of Representable::Definition
|
85
|
+
|
86
|
+
subject.remove(:genre)
|
87
|
+
subject.get(:genre).must_equal nil
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
|
68
92
|
describe "#each" do
|
69
93
|
before { subject.add(:title, {:me => true}) }
|
70
94
|
|
@@ -84,14 +108,6 @@ class ConfigTest < MiniTest::Spec
|
|
84
108
|
end
|
85
109
|
end
|
86
110
|
|
87
|
-
|
88
|
-
describe "#add" do
|
89
|
-
subject { Representable::Config.new.add(:title, {:me => true}) }
|
90
|
-
|
91
|
-
it { subject.must_be_kind_of Representable::Definition }
|
92
|
-
it { subject[:me].must_equal true }
|
93
|
-
end
|
94
|
-
|
95
111
|
describe "#get" do
|
96
112
|
subject { Representable::Config.new }
|
97
113
|
|
@@ -105,7 +121,7 @@ class ConfigTest < MiniTest::Spec
|
|
105
121
|
end
|
106
122
|
|
107
123
|
|
108
|
-
describe "
|
124
|
+
describe "#inherit!" do
|
109
125
|
let (:title) { Definition.new(:title) }
|
110
126
|
let (:length) { Definition.new(:length) }
|
111
127
|
let (:stars) { Definition.new(:stars) }
|
data/test/definition_test.rb
CHANGED
@@ -88,6 +88,16 @@ class DefinitionTest < MiniTest::Spec
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
|
+
|
92
|
+
# delete!
|
93
|
+
describe "#delete!" do
|
94
|
+
let (:definition) { Definition.new(:song, serialize: "remove me!") }
|
95
|
+
|
96
|
+
before { definition[:serialize].evaluate(nil).must_equal "remove me!" }
|
97
|
+
|
98
|
+
it { definition.delete!(:serialize)[:serialize].must_equal nil }
|
99
|
+
end
|
100
|
+
|
91
101
|
# #inspect
|
92
102
|
describe "#inspect" do
|
93
103
|
it { Definition.new(:songs).inspect.must_equal "#<Representable::Definition ==>songs @options={:parse_filter=>[], :render_filter=>[], :as=>\"songs\"}>" }
|
data/test/schema_test.rb
CHANGED
@@ -120,4 +120,39 @@ class SchemaTest < MiniTest::Spec
|
|
120
120
|
it do
|
121
121
|
InheritFromDecorator.new(band).to_hash.must_equal({"genre"=>"Punkrock", "label"=>{"name"=>"Fat Wreck", "city"=>"San Francisco", "employees"=>[{"name"=>"Mike"}], "location"=>{"city"=>"Sanfran"}}})
|
122
122
|
end
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
class ApplyTest < MiniTest::Spec
|
127
|
+
class AlbumDecorator < Representable::Decorator
|
128
|
+
property :title
|
129
|
+
|
130
|
+
property :hit do
|
131
|
+
property :title
|
132
|
+
end
|
133
|
+
|
134
|
+
collection :songs do
|
135
|
+
property :title
|
136
|
+
end
|
137
|
+
|
138
|
+
property :band do # yepp, people do crazy stuff like that.
|
139
|
+
property :label do
|
140
|
+
property :name
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# #apply
|
146
|
+
it do
|
147
|
+
properties = []
|
148
|
+
|
149
|
+
AlbumDecorator.apply do |dfn|
|
150
|
+
properties << dfn.name
|
151
|
+
dfn.merge! :cool => true
|
152
|
+
end.must_equal AlbumDecorator
|
153
|
+
|
154
|
+
properties.must_equal ["title", "hit", "title", "songs", "title", "band", "label", "name"]
|
155
|
+
# writeable
|
156
|
+
AlbumDecorator.representable_attrs.get(:band).representer_module.representable_attrs.get(:label).representer_module.representable_attrs.get(:name)[:cool].must_equal true
|
157
|
+
end
|
123
158
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: representable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -168,10 +168,12 @@ files:
|
|
168
168
|
- TODO
|
169
169
|
- lib/representable.rb
|
170
170
|
- lib/representable/TODO.getting_serious
|
171
|
+
- lib/representable/apply.rb
|
171
172
|
- lib/representable/autoload.rb
|
172
173
|
- lib/representable/binding.rb
|
173
174
|
- lib/representable/coercion.rb
|
174
175
|
- lib/representable/config.rb
|
176
|
+
- lib/representable/debug.rb
|
175
177
|
- lib/representable/declarative.rb
|
176
178
|
- lib/representable/decorator.rb
|
177
179
|
- lib/representable/definition.rb
|