representable 2.4.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +7 -12
  3. data/CHANGES.md +6 -27
  4. data/README.md +28 -1326
  5. data/lib/representable.rb +4 -14
  6. data/lib/representable/binding.rb +3 -7
  7. data/lib/representable/definition.rb +1 -2
  8. data/lib/representable/populator.rb +35 -0
  9. data/lib/representable/version.rb +1 -1
  10. data/test/definition_test.rb +0 -7
  11. data/test/exec_context_test.rb +2 -2
  12. data/test/instance_test.rb +0 -19
  13. data/test/realistic_benchmark.rb +0 -13
  14. data/test/representable_test.rb +0 -16
  15. data/test/skip_test.rb +1 -1
  16. data/test/test_helper.rb +0 -2
  17. metadata +3 -65
  18. data/lib/representable/deprecations.rb +0 -127
  19. data/lib/representable/parse_strategies.rb +0 -93
  20. data/test-with-deprecations/as_test.rb +0 -65
  21. data/test-with-deprecations/benchmarking.rb +0 -83
  22. data/test-with-deprecations/binding_test.rb +0 -46
  23. data/test-with-deprecations/blaaaaaaaa_test.rb +0 -69
  24. data/test-with-deprecations/cached_test.rb +0 -147
  25. data/test-with-deprecations/class_test.rb +0 -119
  26. data/test-with-deprecations/coercion_test.rb +0 -52
  27. data/test-with-deprecations/config/inherit_test.rb +0 -135
  28. data/test-with-deprecations/config_test.rb +0 -122
  29. data/test-with-deprecations/decorator_scope_test.rb +0 -28
  30. data/test-with-deprecations/decorator_test.rb +0 -96
  31. data/test-with-deprecations/default_test.rb +0 -34
  32. data/test-with-deprecations/defaults_options_test.rb +0 -93
  33. data/test-with-deprecations/definition_test.rb +0 -264
  34. data/test-with-deprecations/example.rb +0 -310
  35. data/test-with-deprecations/examples/object.rb +0 -31
  36. data/test-with-deprecations/exec_context_test.rb +0 -93
  37. data/test-with-deprecations/features_test.rb +0 -70
  38. data/test-with-deprecations/filter_test.rb +0 -57
  39. data/test-with-deprecations/for_collection_test.rb +0 -74
  40. data/test-with-deprecations/generic_test.rb +0 -116
  41. data/test-with-deprecations/getter_setter_test.rb +0 -21
  42. data/test-with-deprecations/hash_bindings_test.rb +0 -87
  43. data/test-with-deprecations/hash_test.rb +0 -160
  44. data/test-with-deprecations/heritage_test.rb +0 -62
  45. data/test-with-deprecations/if_test.rb +0 -79
  46. data/test-with-deprecations/include_exclude_test.rb +0 -88
  47. data/test-with-deprecations/inherit_test.rb +0 -159
  48. data/test-with-deprecations/inline_test.rb +0 -272
  49. data/test-with-deprecations/instance_test.rb +0 -266
  50. data/test-with-deprecations/is_representable_test.rb +0 -77
  51. data/test-with-deprecations/json_test.rb +0 -355
  52. data/test-with-deprecations/lonely_test.rb +0 -239
  53. data/test-with-deprecations/mongoid_test.rb +0 -31
  54. data/test-with-deprecations/nested_test.rb +0 -115
  55. data/test-with-deprecations/object_test.rb +0 -60
  56. data/test-with-deprecations/parse_pipeline_test.rb +0 -64
  57. data/test-with-deprecations/parse_strategy_test.rb +0 -279
  58. data/test-with-deprecations/pass_options_test.rb +0 -27
  59. data/test-with-deprecations/pipeline_test.rb +0 -277
  60. data/test-with-deprecations/populator_test.rb +0 -105
  61. data/test-with-deprecations/prepare_test.rb +0 -67
  62. data/test-with-deprecations/private_options_test.rb +0 -18
  63. data/test-with-deprecations/reader_writer_test.rb +0 -19
  64. data/test-with-deprecations/realistic_benchmark.rb +0 -115
  65. data/test-with-deprecations/render_nil_test.rb +0 -21
  66. data/test-with-deprecations/represent_test.rb +0 -88
  67. data/test-with-deprecations/representable_test.rb +0 -511
  68. data/test-with-deprecations/schema_test.rb +0 -148
  69. data/test-with-deprecations/serialize_deserialize_test.rb +0 -33
  70. data/test-with-deprecations/skip_test.rb +0 -81
  71. data/test-with-deprecations/stringify_hash_test.rb +0 -41
  72. data/test-with-deprecations/test_helper.rb +0 -135
  73. data/test-with-deprecations/test_helper_test.rb +0 -25
  74. data/test-with-deprecations/uncategorized_test.rb +0 -67
  75. data/test-with-deprecations/user_options_test.rb +0 -15
  76. data/test-with-deprecations/wrap_test.rb +0 -152
  77. data/test-with-deprecations/xml_bindings_test.rb +0 -62
  78. data/test-with-deprecations/xml_test.rb +0 -503
  79. data/test-with-deprecations/yaml_test.rb +0 -162
  80. data/test/parse_strategy_test.rb +0 -279
@@ -1,239 +0,0 @@
1
- require 'test_helper'
2
-
3
- require 'representable/json/hash'
4
-
5
- class LonelyRepresenterTest < MiniTest::Spec
6
-
7
- # test ::items without arguments, render-only.
8
- for_formats(
9
- :hash => [Representable::Hash::Collection, [{"name"=>"Resist Stance"}, {"name"=>"Suffer"}]],
10
- :json => [Representable::JSON::Collection, "[{\"name\":\"Resist Stance\"},{\"name\":\"Suffer\"}]"],
11
- :xml => [Representable::XML::Collection, "<array><song><name>Resist Stance</name></song><song><name>Suffer</name></song></array>"],
12
- ) do |format, mod, output, input|
13
-
14
- describe "[#{format}] lonely collection, render-only" do # TODO: introduce :representable option?
15
- let (:format) { format }
16
-
17
- representer!(module: mod) do
18
- items do
19
- property :name
20
- end
21
- end
22
-
23
- let (:album) { [Song.new("Resist Stance"), Song.new("Suffer")].extend(representer) }
24
-
25
- it "calls #to_hash on song instances, nothing else" do
26
- render(album).must_equal_document(output)
27
- end
28
- end
29
- end
30
-
31
-
32
-
33
- module SongRepresenter
34
- include Representable::JSON
35
-
36
- property :name
37
- end
38
-
39
- let (:decorator) { rpr = representer; Class.new(Representable::Decorator) { include Representable::Hash; include rpr } }
40
-
41
- describe "JSON::Collection" do
42
- let (:songs) { [Song.new("Days Go By"), Song.new("Can't Take Them All")] }
43
- let (:json) { "[{\"name\":\"Days Go By\"},{\"name\":\"Can't Take Them All\"}]" }
44
-
45
- describe "with contained objects" do
46
- let (:representer) {
47
- Module.new do
48
- include Representable::JSON::Collection
49
- items :class => Song, :extend => SongRepresenter
50
- end
51
- }
52
-
53
-
54
- it "renders array" do
55
- assert_json json, songs.extend(representer).to_json
56
- end
57
-
58
- it "renders array with decorator" do
59
- assert_json json, decorator.new(songs).to_json
60
- end
61
-
62
- it "parses array" do
63
- [].extend(representer).from_json(json).must_equal songs
64
- end
65
-
66
- it "parses array with decorator" do
67
- decorator.new([]).from_json(json).must_equal songs
68
- end
69
- end
70
-
71
- describe "with inline representer" do
72
- representer!(:module => Representable::JSON::Collection) do
73
- items :class => Song do
74
- property :name
75
- end
76
- end
77
-
78
- it { songs.extend(representer).to_json.must_equal json }
79
- it { [].extend(representer).from_json(json).must_equal songs }
80
- end
81
-
82
- describe "with contained text" do
83
- let (:representer) {
84
- Module.new do
85
- include Representable::JSON::Collection
86
- end
87
- }
88
- let (:songs) { ["Days Go By", "Can't Take Them All"] }
89
- let (:json) { "[\"Days Go By\",\"Can't Take Them All\"]" }
90
-
91
- it "renders contained items #to_json" do
92
- assert_json json, songs.extend(representer).to_json
93
- end
94
-
95
- it "returns objects array from #from_json" do
96
- [].extend(representer).from_json(json).must_equal songs
97
- end
98
- end
99
- end
100
-
101
- describe "Hash::Collection with dynamic options" do
102
- class One < Representable::Decorator
103
- def to_hash(*); "One: #{represented}"; end
104
- end
105
-
106
- class Two < Representable::Decorator
107
- def to_hash(*); "Two: #{represented}"; end
108
- end
109
-
110
- representer!(module: Representable::Hash::Collection) do
111
- items extend: ->(options) { options[:input] == 1 ? options[:user_options][:one] : options[:user_options][:two] }
112
- end
113
-
114
-
115
- it { [1,2].extend(representer).to_hash(one: One, two: Two).must_equal(["One: 1", "Two: 2"]) }
116
- end
117
-
118
-
119
- describe "JSON::Hash" do # TODO: move to HashTest.
120
- describe "with contained objects" do
121
- let (:representer) {
122
- Module.new do
123
- include Representable::JSON::Hash
124
- values :class => Song, :extend => SongRepresenter
125
- end
126
- }
127
- let (:json) { "{\"one\":{\"name\":\"Days Go By\"},\"two\":{\"name\":\"Can't Take Them All\"}}" }
128
- let (:songs) { {"one" => Song.new("Days Go By"), "two" => Song.new("Can't Take Them All")} }
129
-
130
- describe "#to_json" do
131
- it "renders hash" do
132
- songs.extend(representer).to_json.must_equal json
133
- end
134
-
135
- it "renders hash with decorator" do
136
- decorator.new(songs).to_json.must_equal json
137
- end
138
-
139
- it "respects :exclude" do
140
- assert_json "{\"two\":{\"name\":\"Can't Take Them All\"}}", {:one => Song.new("Days Go By"), :two => Song.new("Can't Take Them All")}.extend(representer).to_json(:exclude => [:one])
141
- end
142
-
143
- it "respects :include" do
144
- assert_json "{\"two\":{\"name\":\"Can't Take Them All\"}}", {:one => Song.new("Days Go By"), :two => Song.new("Can't Take Them All")}.extend(representer).to_json(:include => [:two])
145
- end
146
- end
147
-
148
- describe "#from_json" do
149
- it "returns objects array" do
150
- {}.extend(representer).from_json(json).must_equal songs
151
- end
152
-
153
- it "parses hash with decorator" do
154
- decorator.new({}).from_json(json).must_equal songs
155
- end
156
-
157
- it "respects :exclude" do
158
- assert_equal({"two" => Song.new("Can't Take Them All")}, {}.extend(representer).from_json(json, :exclude => [:one]))
159
- end
160
-
161
- it "respects :include" do
162
- assert_equal({"one" => Song.new("Days Go By")}, {}.extend(representer).from_json(json, :include => [:one]))
163
- end
164
- end
165
-
166
-
167
- describe "with inline representer" do
168
- representer!(:module => Representable::JSON::Hash) do
169
- values :class => Song do
170
- property :name
171
- end
172
- end
173
-
174
- it { songs.extend(representer).to_json.must_equal json }
175
- it { {}.extend(representer).from_json(json).must_equal songs }
176
- end
177
- end
178
-
179
-
180
- describe "with scalar" do
181
- let (:representer) {
182
- Module.new do
183
- include Representable::JSON::Hash
184
- end
185
- }
186
- let (:json) { %{{"one":1,"two":2}} }
187
- let (:data) { {one: 2, two: 3} }
188
-
189
- describe "#to_json" do
190
- it { data.extend(representer).to_json.must_equal %{{"one":2,"two":3}} }
191
-
192
- # it "respects :exclude" do
193
- # assert_json "{\"two\":{\"name\":\"Can't Take Them All\"}}", {:one => Song.new("Days Go By"), :two => Song.new("Can't Take Them All")}.extend(representer).to_json(:exclude => [:one])
194
- # end
195
-
196
- # it "respects :include" do
197
- # assert_json "{\"two\":{\"name\":\"Can't Take Them All\"}}", {:one => Song.new("Days Go By"), :two => Song.new("Can't Take Them All")}.extend(representer).to_json(:include => [:two])
198
- # end
199
- end
200
-
201
- describe "#from_json" do # FIXME: what's the point of this?
202
- it { data.extend(representer).from_hash(data).must_equal data }
203
- end
204
- end
205
-
206
-
207
- describe "with contained text" do
208
- before do
209
- @songs_representer = Module.new do
210
- include Representable::JSON::Collection
211
- end
212
- end
213
-
214
- it "renders contained items #to_json" do
215
- assert_json "[\"Days Go By\",\"Can't Take Them All\"]", ["Days Go By", "Can't Take Them All"].extend(@songs_representer).to_json
216
- end
217
-
218
- it "returns objects array from #from_json" do
219
- assert_equal ["Days Go By", "Can't Take Them All"], [].extend(@songs_representer).from_json("[\"Days Go By\",\"Can't Take Them All\"]")
220
- end
221
- end
222
- end
223
- end
224
-
225
-
226
- # describe "Hash::Collection with :include" do
227
- class CollectionWithIncludeTest < MiniTest::Spec
228
- Song = Struct.new(:id, :title)
229
-
230
- representer!(decorator: true, module: Representable::Hash::Collection) do
231
- items do
232
- property :id
233
- property :title
234
- end
235
- end
236
-
237
- it { representer.new([Song.new(1, "ACAB")]).to_hash.must_equal([{"id"=>1, "title"=>"ACAB"}]) }
238
- it { representer.new([Song.new(1, "ACAB")]).to_hash(include: [:title]).must_equal([{"title"=>"ACAB"}]) }
239
- end
@@ -1,31 +0,0 @@
1
- require 'test_helper'
2
- require 'mongoid'
3
- require 'mongoid/document'
4
-
5
- class MongoidTest < MiniTest::Spec
6
- describe "Mongoid compatibility" do
7
- it "allows #to_json" do
8
- class Profile
9
- include Mongoid::Document
10
- field :name
11
- end
12
-
13
- class Dude
14
- include Mongoid::Document
15
- embeds_one :profile, :class_name => "MongoidTest::Profile"
16
- end
17
-
18
- module ProfileRepresenter
19
- include Representable::JSON
20
-
21
- property :name
22
- end
23
-
24
- dude = Dude.new
25
- dude.profile = Profile.new
26
- dude.profile.name = "Kofi"
27
-
28
- assert_equal "{\"name\":\"Kofi\"}", dude.profile.extend(ProfileRepresenter).to_json
29
- end
30
- end
31
- end
@@ -1,115 +0,0 @@
1
- require 'test_helper'
2
-
3
- class NestedTest < MiniTest::Spec
4
- Album = Struct.new(:label, :owner, :amount)
5
-
6
- for_formats(
7
- :hash => [Representable::Hash, {"label" => {"label"=>"Epitaph", "owner"=>"Brett Gurewitz", "releases"=>{"amount"=>19}}}],
8
- # :xml => [Representable::XML, "<open_struct></open_struct>"],
9
- :yaml => [Representable::YAML, "---\nlabel:\n label: Epitaph\n owner: Brett Gurewitz\n releases:\n amount: 19\n"]
10
- ) do |format, mod, output, input|
11
-
12
- [false, true].each do |is_decorator|
13
- describe "::nested with (inline representer|decorator): #{is_decorator}" do
14
- let (:format) { format }
15
-
16
- representer!(:module => mod, :decorator => is_decorator) do
17
- nested :label do
18
- property :label
19
- property :owner
20
-
21
- # self.representation_wrap = nil if format == :xml
22
- nested :releases do
23
- property :amount
24
- end
25
- end
26
-
27
- # self.representation_wrap = :album if format == :xml
28
- end
29
-
30
- let (:album) { Album.new("Epitaph", "Brett Gurewitz", 19) }
31
- let (:decorator) { representer.prepare(album) }
32
-
33
- it "renders nested Album-properties in separate section" do
34
- render(decorator).must_equal_document output
35
-
36
- # do not use extend on the nested object. # FIXME: make this a proper test with two describes instead of this pseudo-meta stuff.
37
- if is_decorator==true
38
- album.wont_be_kind_of(Representable::Hash)
39
- end
40
- end
41
-
42
- it "parses nested properties to Album instance" do
43
- album = parse(representer.prepare(Album.new), output)
44
- album.label.must_equal "Epitaph"
45
- album.owner.must_equal "Brett Gurewitz"
46
- end
47
- end
48
- end
49
-
50
-
51
- describe "Decorator ::nested with extend:" do
52
- let (:format) { format }
53
-
54
- representer!(:name => :label_rpr) do
55
- include mod
56
- property :label
57
- property :owner
58
-
59
- nested :releases do # DISCUSS: do we need to test this?
60
- property :amount
61
- end
62
- end
63
-
64
- representer!(:module => mod, :decorator => true, :inject => :label_rpr) do
65
- nested :label, :extend => label_rpr
66
-
67
- self.representation_wrap = :album if format == :xml
68
- end
69
-
70
- let (:album) { representer.prepare(Album.new("Epitaph", "Brett Gurewitz", 19)) }
71
-
72
- # TODO: shared example with above.
73
- it "renders nested Album-properties in separate section" do
74
- render(album).must_equal_document output
75
- end
76
-
77
- it "parses nested properties to Album instance" do
78
- album = parse(representer.prepare(Album.new), output)
79
- album.label.must_equal "Epitaph"
80
- album.owner.must_equal "Brett Gurewitz"
81
- album.amount.must_equal 19
82
- end
83
- end
84
- end
85
-
86
-
87
- describe "::nested without block but with inherit:" do
88
-
89
- representer!(:name => :parent) do
90
- include Representable::Hash
91
-
92
- nested :label do
93
- property :owner
94
- end
95
- end
96
-
97
- representer!(:module => Representable::Hash, :inject => :parent) do
98
- include parent
99
- nested :label, :inherit => true, :as => "Label"
100
- end
101
-
102
- let (:album) { representer.prepare(Album.new("Epitaph", "Brett Gurewitz", 19)) }
103
-
104
- it "renders nested Album-properties in separate section" do
105
- representer.prepare(album).to_hash.must_equal({"Label"=>{"owner"=>"Brett Gurewitz"}})
106
- end
107
-
108
- # it "parses nested properties to Album instance" do
109
- # album = parse(representer.prepare(Album.new), output)
110
- # album.label.must_equal "Epitaph"
111
- # album.owner.must_equal "Brett Gurewitz"
112
- # album.amount.must_equal 19
113
- # end
114
- end
115
- end
@@ -1,60 +0,0 @@
1
- require "test_helper"
2
- require "representable/object"
3
-
4
- class ObjectTest < MiniTest::Spec
5
- Song = Struct.new(:title, :album)
6
- Album = Struct.new(:name, :songs)
7
-
8
- representer!(module: Representable::Object) do
9
- property :title
10
-
11
- property :album, instance: lambda { |fragment, *| fragment.name.upcase!; fragment } do
12
- property :name
13
-
14
- collection :songs, instance: lambda { |fragment, *| fragment.title.upcase!; fragment } do
15
- property :title
16
- end
17
- end
18
- # TODO: collection
19
- end
20
-
21
- let (:source) { Song.new("The King Is Dead", Album.new("Ruiner", [Song.new("In Vino Veritas II")])) }
22
- let (:target) { Song.new }
23
-
24
- it do
25
- representer.prepare(target).from_object(source)
26
-
27
- target.title.must_equal "The King Is Dead"
28
- target.album.name.must_equal "RUINER"
29
- target.album.songs[0].title.must_equal "IN VINO VERITAS II"
30
- end
31
-
32
- # ignore nested object when nil
33
- it do
34
- representer.prepare(Song.new("The King Is Dead")).from_object(Song.new)
35
-
36
- target.title.must_equal nil # scalar property gets overridden when nil.
37
- target.album.must_equal nil # nested property stays nil.
38
- end
39
-
40
- # to_object
41
- describe "#to_object" do
42
- representer!(module: Representable::Object) do
43
- property :title
44
-
45
- property :album, render_filter: lambda { |object, *| object.name = "Live"; object } do
46
- property :name
47
-
48
- collection :songs, render_filter: lambda { |object, *| object[0].title = 1; object } do
49
- property :title
50
- end
51
- end
52
- end
53
-
54
- it do
55
- representer.prepare(source).to_object
56
- source.album.name.must_equal "Live"
57
- source.album.songs[0].title.must_equal 1
58
- end
59
- end
60
- end
@@ -1,64 +0,0 @@
1
- require "test_helper"
2
-
3
- class ParsePipelineTest < MiniTest::Spec
4
- Album = Struct.new(:id, :artist, :songs)
5
- Artist = Struct.new(:email)
6
- Song = Struct.new(:title)
7
-
8
- describe "transforming nil to [] when parsing" do
9
- representer!(decorator: true) do
10
- collection :songs,
11
- parse_pipeline: ->(*) {
12
- Representable::Pipeline.insert(
13
- parse_functions, # original function list from Binding#parse_functions.
14
- ->(input, options) { input.nil? ? [] : input }, # your new function (can be any callable object)..
15
- replace: Representable::OverwriteOnNil # ..that replaces the original function.
16
- )
17
- },
18
- class: Song do
19
- property :title
20
- end
21
- end
22
-
23
- it do
24
- representer.new(album = Album.new).from_hash("songs"=>nil)
25
- album.songs.must_equal []
26
- end
27
-
28
- it do
29
- representer.new(album = Album.new).from_hash("songs"=>[{"title" => "Business Conduct"}])
30
- album.songs.must_equal [Song.new("Business Conduct")]
31
- end
32
- end
33
-
34
-
35
- # tests [Collect[Instance, Prepare, Deserialize], Setter]
36
- class Representer < Representable::Decorator
37
- include Representable::Hash
38
-
39
- # property :artist, populator: Uber::Options::Value.new(ArtistPopulator.new), pass_options:true do
40
- # property :email
41
- # end
42
- # DISCUSS: rename to populator_pipeline ?
43
- collection :songs, parse_pipeline: ->(*) { [Collect[Instance, Prepare, Deserialize], Setter] }, instance: :instance!, exec_context: :decorator, pass_options: true do
44
- property :title
45
- end
46
-
47
- def instance!(*options)
48
- puts "@@@@@ #{options.inspect}"
49
- Song.new
50
- end
51
-
52
- def songs=(array)
53
- represented.songs=array
54
- end
55
- end
56
-
57
- it do
58
- skip "TODO: implement :parse_pipeline and :render_pipeline, and before/after/replace semantics"
59
- album = Album.new
60
- Representer.new(album).from_hash({"artist"=>{"email"=>"yo"}, "songs"=>[{"title"=>"Affliction"}, {"title"=>"Dream Beater"}]})
61
- album.songs.must_equal([Song.new("Affliction"), Song.new("Dream Beater")])
62
- puts album.inspect
63
- end
64
- end