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,57 +0,0 @@
1
- require 'test_helper'
2
-
3
- class FilterPipelineTest < MiniTest::Spec
4
- let (:block1) { lambda { |input, options| "1: #{input}" } }
5
- let (:block2) { lambda { |input, options| "2: #{input}" } }
6
-
7
- subject { Representable::Pipeline[block1, block2] }
8
-
9
- it { subject.call("Horowitz", {}).must_equal "2: 1: Horowitz" }
10
- end
11
-
12
-
13
- class FilterTest < MiniTest::Spec
14
- representer! do
15
- property :title
16
-
17
- property :track,
18
- :parse_filter => lambda { |input, options| "#{input.downcase},#{options[:doc]}" },
19
- :render_filter => lambda { |val, options| "#{val.upcase},#{options[:doc]},#{options[:options][:user_options]}" }
20
- end
21
-
22
- # gets doc and options.
23
- it {
24
- song = OpenStruct.new.extend(representer).from_hash("title" => "VULCAN EARS", "track" => "Nine")
25
- song.title.must_equal "VULCAN EARS"
26
- song.track.must_equal "nine,{\"title\"=>\"VULCAN EARS\", \"track\"=>\"Nine\"}"
27
- }
28
-
29
- it { OpenStruct.new("title" => "vulcan ears", "track" => "Nine").extend(representer).to_hash.must_equal( {"title"=>"vulcan ears", "track"=>"NINE,{\"title\"=>\"vulcan ears\"},{}"}) }
30
-
31
-
32
- describe "#parse_filter" do
33
- representer! do
34
- property :track,
35
- :parse_filter => [
36
- lambda { |input, options| "#{input}-1" },
37
- lambda { |input, options| "#{input}-2" }],
38
- :render_filter => [
39
- lambda { |val, options| "#{val}-1" },
40
- lambda { |val, options| "#{val}-2" }]
41
- end
42
-
43
- # order matters.
44
- it { OpenStruct.new.extend(representer).from_hash("track" => "Nine").track.must_equal "Nine-1-2" }
45
- it { OpenStruct.new("track" => "Nine").extend(representer).to_hash.must_equal({"track"=>"Nine-1-2"}) }
46
- end
47
- end
48
-
49
-
50
- # class RenderFilterTest < MiniTest::Spec
51
- # representer! do
52
- # property :track, :render_filter => [lambda { |val, options| "#{val}-1" } ]
53
- # property :track, :render_filter => [lambda { |val, options| "#{val}-2" } ], :inherit => true
54
- # end
55
-
56
- # it { OpenStruct.new("track" => "Nine").extend(representer).to_hash.must_equal({"track"=>"Nine-1-2"}) }
57
- # end
@@ -1,74 +0,0 @@
1
- require 'test_helper'
2
-
3
- class ForCollectionTest < MiniTest::Spec
4
- module SongRepresenter
5
- include Representable::JSON
6
-
7
- property :name
8
- end
9
-
10
- let (:songs) { [Song.new("Days Go By"), Song.new("Can't Take Them All")] }
11
- let (:json) { "[{\"name\":\"Days Go By\"},{\"name\":\"Can't Take Them All\"}]" }
12
-
13
-
14
- # Module.for_collection
15
- # Decorator.for_collection
16
- for_formats(
17
- :hash => [Representable::Hash, out=[{"name" => "Days Go By"}, {"name"=>"Can't Take Them All"}], out],
18
- :json => [Representable::JSON, out="[{\"name\":\"Days Go By\"},{\"name\":\"Can't Take Them All\"}]", out],
19
- # :xml => [Representable::XML, out="<a><song></song><song></song></a>", out]
20
- ) do |format, mod, output, input|
21
-
22
- describe "Module::for_collection [#{format}]" do
23
- let (:format) { format }
24
-
25
- let (:representer) {
26
- Module.new do
27
- include mod
28
- property :name#, :as => :title
29
-
30
- collection_representer :class => Song
31
-
32
- # self.representation_wrap = :songs if format == :xml
33
- end
34
- }
35
-
36
- it { render(songs.extend(representer.for_collection)).must_equal_document output }
37
- it { render(representer.for_collection.prepare(songs)).must_equal_document output }
38
- # parsing needs the class set, at least
39
- it { parse([].extend(representer.for_collection), input).must_equal songs }
40
- end
41
-
42
- describe "Module::for_collection without configuration [#{format}]" do
43
- let (:format) { format }
44
-
45
- let (:representer) {
46
- Module.new do
47
- include mod
48
- property :name
49
- end
50
- }
51
-
52
- # rendering works out of the box, no config necessary
53
- it { render(songs.extend(representer.for_collection)).must_equal_document output }
54
- end
55
-
56
-
57
- describe "Decorator::for_collection [#{format}]" do
58
- let (:format) { format }
59
- let (:representer) {
60
- Class.new(Representable::Decorator) do
61
- include mod
62
- property :name
63
-
64
- collection_representer :class => Song
65
- end
66
- }
67
-
68
- it { render(representer.for_collection.new(songs)).must_equal_document output }
69
- it { parse(representer.for_collection.new([]), input).must_equal songs }
70
- end
71
- end
72
-
73
- # with module including module
74
- end
@@ -1,116 +0,0 @@
1
- require 'test_helper'
2
-
3
- class GenericTest < MiniTest::Spec # TODO: rename/restructure to CollectionTest.
4
- let (:new_album) { OpenStruct.new.extend(representer) }
5
- let (:album) { OpenStruct.new(:songs => ["Fuck Armageddon"]).extend(representer) }
6
- let (:song) { OpenStruct.new(:title => "Resist Stance") }
7
- let (:song_representer) { Module.new do include Representable::Hash; property :title end }
8
-
9
-
10
- describe "::collection" do
11
- representer! do
12
- collection :songs
13
- end
14
-
15
- it "doesn't initialize property" do
16
- new_album.from_hash({})
17
- new_album.songs.must_equal nil
18
- end
19
-
20
- it "leaves properties untouched" do
21
- album.from_hash({})
22
- # TODO: test property.
23
- album.songs.must_equal ["Fuck Armageddon"] # when the collection is not present in the incoming hash, this propery stays untouched.
24
- end
25
-
26
-
27
- # when collection is nil, it doesn't get rendered:
28
- for_formats(
29
- :hash => [Representable::Hash, {}],
30
- :xml => [Representable::XML, "<open_struct></open_struct>"],
31
- :yaml => [Representable::YAML, "--- {}\n"], # FIXME: this doesn't look right.
32
- ) do |format, mod, output, input|
33
-
34
- describe "nil collections" do
35
- let (:format) { format }
36
-
37
- representer!(:module => mod) do
38
- collection :songs
39
- self.representation_wrap = :album if format == :xml
40
- end
41
-
42
- let (:album) { Album.new.extend(representer) }
43
-
44
- it "doesn't render collection in #{format}" do
45
- render(album).must_equal_document output
46
- end
47
- end
48
- end
49
-
50
- # when collection is set but empty, render the empty collection.
51
- for_formats(
52
- :hash => [Representable::Hash, {"songs" => []}],
53
- #:xml => [Representable::XML, "<open_struct><songs/></open_struct>"],
54
- :yaml => [Representable::YAML, "---\nsongs: []\n"],
55
- ) do |format, mod, output, input|
56
-
57
- describe "empty collections" do
58
- let (:format) { format }
59
-
60
- representer!(:module => mod) do
61
- collection :songs
62
- self.representation_wrap = :album if format == :xml
63
- end
64
-
65
- let (:album) { OpenStruct.new(:songs => []).extend(representer) }
66
-
67
- it "renders empty collection in #{format}" do
68
- render(album).must_equal_document output
69
- end
70
- end
71
- end
72
-
73
-
74
- # when collection is [], suppress rendering when render_empty: false.
75
- for_formats(
76
- :hash => [Representable::Hash, {}],
77
- #:xml => [Representable::XML, "<open_struct><songs/></open_struct>"],
78
- :yaml => [Representable::YAML, "--- {}\n"],
79
- ) do |format, mod, output, input|
80
-
81
- describe "render_empty [#{format}]" do
82
- let (:format) { format }
83
-
84
- representer!(:module => mod) do
85
- collection :songs, :render_empty => false
86
- self.representation_wrap = :album if format == :xml
87
- end
88
-
89
- let (:album) { OpenStruct.new(:songs => []).extend(representer) }
90
-
91
- it { render(album).must_equal_document output }
92
- end
93
- end
94
- end
95
-
96
-
97
- # wrap_test
98
- for_formats(
99
- :hash => [Representable::Hash, {}],
100
- # :xml => [Representable::XML, "<open_struct>\n <song>\n <name>Alive</name>\n </song>\n</open_struct>", "<open_struct><song><name>You've Taken Everything</name></song>/open_struct>"],
101
- # :yaml => [Representable::YAML, "---\nsong:\n name: Alive\n", "---\nsong:\n name: You've Taken Everything\n"],
102
- ) do |format, mod, input|
103
-
104
- describe "parsing [#{format}] with wrap where wrap is missing" do
105
- representer!(:module => mod) do
106
- self.representation_wrap = :song
107
-
108
- property :title
109
- end
110
-
111
- it "doesn't change represented object" do
112
- song.extend(representer).send("from_#{format}", input).title.must_equal "Resist Stance"
113
- end
114
- end
115
- end
116
- end
@@ -1,21 +0,0 @@
1
- require 'test_helper'
2
-
3
- class GetterSetterTest < BaseTest
4
- representer! do
5
- property :name, # key under :name.
6
- :getter => lambda { |args| "#{args[:welcome]} #{song_name}" },
7
- :setter => lambda { |val, args| self.song_name = "#{args[:welcome]} #{val}" }
8
- end
9
-
10
- subject { Struct.new(:song_name).new("Mony Mony").extend(representer) }
11
-
12
- it "uses :getter when rendering" do
13
- subject.instance_eval { def name; raise; end }
14
- subject.to_hash(:welcome => "Hi").must_equal({"name" => "Hi Mony Mony"})
15
- end
16
-
17
- it "uses :setter when parsing" do
18
- subject.instance_eval { def name=(*); raise; end; self }
19
- subject.from_hash({"name" => "Eyes Without A Face"}, :welcome => "Hello").song_name.must_equal "Hello Eyes Without A Face"
20
- end
21
- end
@@ -1,87 +0,0 @@
1
- require 'test_helper'
2
-
3
- class HashBindingTest < MiniTest::Spec
4
- module SongRepresenter
5
- include Representable::JSON
6
- property :name
7
- end
8
-
9
- class SongWithRepresenter < ::Song
10
- include Representable
11
- include SongRepresenter
12
- end
13
-
14
-
15
- describe "PropertyBinding" do
16
- describe "#read" do
17
- before do
18
- @property = Representable::Hash::Binding.new(Representable::Definition.new(:song))
19
- end
20
-
21
- it "returns fragment if present" do
22
- assert_equal "Stick The Flag Up Your Goddamn Ass, You Sonofabitch", @property.read({"song" => "Stick The Flag Up Your Goddamn Ass, You Sonofabitch"}, "song")
23
- assert_equal "", @property.read({"song" => ""}, "song")
24
- assert_equal nil, @property.read({"song" => nil}, "song")
25
- end
26
-
27
- it "returns FRAGMENT_NOT_FOUND if not in document" do
28
- assert_equal Representable::Binding::FragmentNotFound, @property.read({}, "song")
29
- end
30
-
31
- end
32
- end
33
-
34
-
35
- describe "CollectionBinding" do
36
- describe "with plain text items" do
37
- before do
38
- @property = Representable::Hash::Binding::Collection.new(Representable::Definition.new(:songs, :collection => true))
39
- end
40
-
41
- it "extracts with #read" do
42
- assert_equal ["The Gargoyle", "Bronx"], @property.read({"songs" => ["The Gargoyle", "Bronx"]}, "songs")
43
- end
44
-
45
- it "inserts with #write" do
46
- doc = {}
47
- assert_equal(["The Gargoyle", "Bronx"], @property.write(doc, ["The Gargoyle", "Bronx"], "songs"))
48
- assert_equal({"songs"=>["The Gargoyle", "Bronx"]}, doc)
49
- end
50
- end
51
- end
52
-
53
-
54
-
55
-
56
- describe "HashBinding" do
57
- describe "with plain text items" do
58
- before do
59
- @property = Representable::Hash::Binding.new(Representable::Definition.new(:songs, :hash => true))
60
- end
61
-
62
- it "extracts with #read" do
63
- assert_equal({"first" => "The Gargoyle", "second" => "Bronx"} , @property.read({"songs" => {"first" => "The Gargoyle", "second" => "Bronx"}}, "songs"))
64
- end
65
-
66
- it "inserts with #write" do
67
- doc = {}
68
- assert_equal({"first" => "The Gargoyle", "second" => "Bronx"}, @property.write(doc, {"first" => "The Gargoyle", "second" => "Bronx"}, "songs"))
69
- assert_equal({"songs"=>{"first" => "The Gargoyle", "second" => "Bronx"}}, doc)
70
- end
71
- end
72
-
73
- describe "with objects" do
74
- before do
75
- @property = Representable::Hash::Binding.new(Representable::Definition.new(:songs, :hash => true, :class => Song, :extend => SongRepresenter))
76
- end
77
-
78
- it "doesn't change the represented hash in #write" do
79
- song = Song.new("Better Than That")
80
- hash = {"first" => song}
81
- @property.write({}, hash, "song")
82
- assert_equal({"first" => song}, hash)
83
- end
84
- end
85
-
86
- end
87
- end
@@ -1,160 +0,0 @@
1
- require 'test_helper'
2
-
3
- class HashWithScalarPropertyTest < MiniTest::Spec
4
- Album = Struct.new(:title)
5
-
6
- representer! do
7
- property :title
8
- end
9
-
10
- let (:album) { Album.new("Liar") }
11
-
12
- describe "#to_hash" do
13
- it "renders plain property" do
14
- album.extend(representer).to_hash.must_equal("title" => "Liar")
15
- end
16
- end
17
-
18
-
19
- describe "#from_hash" do
20
- it "parses plain property" do
21
- album.extend(representer).from_hash("title" => "This Song Is Recycled").title.must_equal "This Song Is Recycled"
22
- end
23
-
24
- # Fixes issue #115
25
- it "allows nil value in the incoming document and corresponding nil value for the represented" do
26
- album = Album.new
27
- album.title.must_equal nil
28
- album.extend(representer).from_hash("title" => nil)
29
- end
30
- end
31
- end
32
-
33
-
34
- class HashWithTypedPropertyTest < MiniTest::Spec
35
- Album = Struct.new(:best_song)
36
-
37
- representer! do
38
- property :best_song, :class => Song do
39
- property :name
40
- end
41
- end
42
-
43
- let (:album) { Album.new(Song.new("Liar")) }
44
-
45
- describe "#to_hash" do
46
- it "renders embedded typed property" do
47
- album.extend(representer).to_hash.must_equal("best_song" => {"name" => "Liar"})
48
- end
49
- end
50
-
51
- describe "#from_hash" do
52
- it "parses embedded typed property" do
53
- album.extend(representer).from_hash("best_song" => {"name" => "Go With Me"})
54
- album.best_song.name.must_equal "Go With Me"
55
- end
56
-
57
- # nested nil removes nested object.
58
- it do
59
- album = Album.new(Song.new("Pre-medicated Murder"))
60
- album.extend(representer).from_hash("best_song" => nil)
61
- album.best_song.must_equal nil
62
- end
63
-
64
- # nested blank hash creates blank object when not populated.
65
- it do
66
- album = Album.new#(Song.new("Pre-medicated Murder"))
67
- album.extend(representer).from_hash("best_song" => {})
68
- album.best_song.name.must_equal nil
69
- end
70
-
71
- # Fixes issue #115
72
- it "allows nil value in the incoming document and corresponding nil value for the represented" do
73
- album = Album.new
74
- album.extend(representer).from_hash("best_song" => nil)
75
- album.best_song.must_equal nil
76
- end
77
- end
78
- end
79
-
80
- # TODO: move to AsTest.
81
- class HashWithTypedPropertyAndAs < MiniTest::Spec
82
- representer! do
83
- property :song, :class => Song, :as => :hit do
84
- property :name
85
- end
86
- end
87
-
88
- let (:album) { OpenStruct.new(:song => Song.new("Liar")).extend(representer) }
89
-
90
- it { album.to_hash.must_equal("hit" => {"name" => "Liar"}) }
91
- it { album.from_hash("hit" => {"name" => "Go With Me"}).must_equal OpenStruct.new(:song => Song.new("Go With Me")) }
92
- end
93
- # # describe "FIXME COMBINE WITH ABOVE with :extend and :as" do
94
- # # hash_song = Module.new do
95
- # # include Representable::XML
96
- # # self.representation_wrap = :song
97
- # # property :name
98
- # # end
99
-
100
- # # let (:hash_album) { Module.new do
101
- # # include Representable::XML
102
- # # self.representation_wrap = :album
103
- # # property :song, :extend => hash_song, :class => Song, :as => :hit
104
- # # end }
105
-
106
- # # let (:album) { OpenStruct.new(:song => Song.new("Liar")).extend(hash_album) }
107
-
108
- # # it { album.to_xml.must_equal_xml("<album><hit><name>Liar</name></hit></album>") }
109
- # # #it { album.from_hash("hit" => {"name" => "Go With Me"}).must_equal OpenStruct.new(:song => Song.new("Go With Me")) }
110
- # # end
111
- # end
112
-
113
-
114
-
115
- class HashWithTypedCollectionTest < MiniTest::Spec
116
- Album = Struct.new(:songs)
117
-
118
- representer! do
119
- collection :songs, class: Song do
120
- property :name
121
- property :track
122
- end
123
- end
124
-
125
- let (:album) { Album.new([Song.new("Liar", 1), Song.new("What I Know", 2)]) }
126
-
127
- describe "#to_hash" do
128
- it "renders collection of typed property" do
129
- album.extend(representer).to_hash.must_equal("songs" => [{"name" => "Liar", "track" => 1}, {"name" => "What I Know", "track" => 2}])
130
- end
131
- end
132
-
133
- describe "#from_hash" do
134
- it "parses collection of typed property" do
135
- album.extend(representer).from_hash("songs" => [{"name" => "One Shot Deal", "track" => 4},
136
- {"name" => "Three Way Dance", "track" => 5}]).must_equal Album.new([Song.new("One Shot Deal", 4), Song.new("Three Way Dance", 5)])
137
- end
138
- end
139
- end
140
-
141
- class HashWithScalarCollectionTest < MiniTest::Spec
142
- Album = Struct.new(:songs)
143
- representer! { collection :songs }
144
-
145
- let (:album) { Album.new(["Jackhammer", "Terrible Man"]) }
146
-
147
-
148
- describe "#to_hash" do
149
- it "renders a block style list per default" do
150
- album.extend(representer).to_hash.must_equal("songs" => ["Jackhammer", "Terrible Man"])
151
- end
152
- end
153
-
154
-
155
- describe "#from_hash" do
156
- it "parses a block style list" do
157
- album.extend(representer).from_hash("songs" => ["Off Key Melody", "Sinking"]).must_equal Album.new(["Off Key Melody", "Sinking"])
158
- end
159
- end
160
- end