representable 2.4.1 → 3.0.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.
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