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,119 +0,0 @@
1
- require 'test_helper'
2
-
3
- class ClassTest < BaseTest
4
-
5
- class RepresentingSong
6
- attr_reader :name
7
-
8
- def from_hash(doc, *args)
9
- @name = doc["__name__"]
10
-
11
- self # DISCUSS: do we wanna be able to return whatever we want here? this is a trick to replace the actual object
12
- end
13
- end
14
-
15
-
16
- describe "class: ClassName, only" do
17
- representer! do
18
- property :song, :class => RepresentingSong # supposed this class exposes #from_hash itself.
19
- end
20
-
21
- it "creates fresh instance and doesn't extend" do
22
- song = representer.prepare(OpenStruct.new).from_hash({"song" => {"__name__" => "Captured"}}).song
23
- song.must_be_instance_of RepresentingSong
24
- song.name.must_equal "Captured"
25
- end
26
- end
27
-
28
-
29
- describe "class: lambda, only" do
30
- representer! do
31
- property :song, :class => lambda { |*| RepresentingSong }
32
- end
33
-
34
- it "creates fresh instance and doesn't extend" do
35
- song = representer.prepare(OpenStruct.new).from_hash({"song" => {"__name__" => "Captured"}}).song
36
- song.must_be_instance_of RepresentingSong
37
- song.name.must_equal "Captured"
38
- end
39
- end
40
-
41
-
42
- # this throws a DeserializationError now.
43
- describe "lambda { nil }" do
44
- representer! do
45
- property :title, :class => nil
46
- end
47
-
48
- it do
49
- assert_raises Representable::DeserializeError do
50
- OpenStruct.new.extend(representer).from_hash({"title" => {}})
51
- end
52
- end
53
- end
54
-
55
-
56
- describe "lambda receiving fragment and args" do
57
- let (:klass) { Class.new do
58
- class << self
59
- attr_accessor :args
60
- end
61
-
62
- def from_hash(*)
63
- self.class.new
64
- end
65
- end }
66
-
67
- representer!(:inject => :klass) do
68
- _klass = klass
69
- property :song, :class => lambda { |fragment, args| _klass.args=([fragment,args]); _klass }
70
- end
71
-
72
- it { representer.prepare(OpenStruct.new).from_hash({"song" => {"name" => "Captured"}}, :volume => true).song.class.args.
73
- must_equal([{"name"=>"Captured"}, {:volume=>true}]) }
74
- end
75
-
76
-
77
- describe "collection: lambda receiving fragment and args" do
78
- let (:klass) { Class.new do
79
- class << self
80
- attr_accessor :args
81
- end
82
-
83
- def from_hash(*)
84
- self.class.new
85
- end
86
- end }
87
-
88
- representer!(:inject => :klass) do
89
- _klass = klass
90
- collection :songs, :class => lambda { |fragment, i, args| _klass.args=([fragment,i,args]); _klass }
91
- end
92
-
93
- it { representer.prepare(OpenStruct.new).from_hash({"songs" => [{"name" => "Captured"}]}, :volume => true).songs.first.class.args.
94
- must_equal([{"name"=>"Captured"}, 0, {:volume=>true}]) }
95
- end
96
-
97
-
98
- describe "class: implementing #from_hash" do
99
- let(:parser) do
100
- Class.new do
101
- def from_hash(*)
102
- [1,2,3,4]
103
- end
104
- end
105
- end
106
-
107
- representer!(:inject => :parser) do
108
- property :song, :class => parser # supposed this class exposes #from_hash itself.
109
- end
110
-
111
- it "allows returning arbitrary objects in #from_hash" do
112
- representer.prepare(OpenStruct.new).from_hash({"song" => 1}).song.must_equal [1,2,3,4]
113
- end
114
- end
115
- end
116
-
117
- #TODO: test fragment,
118
-
119
- # `class: Song` only, no :extend.
@@ -1,52 +0,0 @@
1
- require 'test_helper'
2
- require 'representable/coercion'
3
-
4
- class VirtusCoercionTest < MiniTest::Spec
5
- representer! do
6
- include Representable::Coercion
7
-
8
- property :title # no coercion.
9
- property :length, :type => Float
10
-
11
- property :band, :class => OpenStruct do
12
- property :founded, :type => Integer
13
- end
14
-
15
- collection :songs, :class => OpenStruct do
16
- property :ok, :type => Virtus::Attribute::Boolean
17
- end
18
- end
19
-
20
- let (:album) { OpenStruct.new(:title => "Dire Straits", :length => 41.34,
21
- :band => OpenStruct.new(:founded => "1977"),
22
- :songs => [OpenStruct.new(:ok => 1), OpenStruct.new(:ok => 0)]) }
23
-
24
- it { album.extend(representer).to_hash.must_equal({"title"=>"Dire Straits", "length"=>41.34, "band"=>{"founded"=>1977}, "songs"=>[{"ok"=>true}, {"ok"=>false}]}) }
25
-
26
- it {
27
- album = OpenStruct.new
28
- album.extend(representer)
29
- album.from_hash({"title"=>"Dire Straits", "length"=>"41.34", "band"=>{"founded"=>"1977"}, "songs"=>[{"ok"=>1}, {"ok"=>0}]})
30
-
31
- # it
32
- album.length.must_equal 41.34
33
- album.band.founded.must_equal 1977
34
- album.songs[0].ok.must_equal true
35
- }
36
-
37
-
38
- describe "with user :parse_filter and :render_filter" do
39
- representer! do
40
- include Representable::Coercion
41
-
42
- property :length, :type => Float,
43
- :parse_filter => lambda { |input, options| "#{input}.1" }, # happens BEFORE coercer.
44
- :render_filter => lambda { |fragment,*| "#{fragment}.1" }
45
- end
46
-
47
- # user's :parse_filter(s) are run before coercion.
48
- it { OpenStruct.new.extend(representer).from_hash("length"=>"1").length.must_equal 1.1 }
49
- # user's :render_filter(s) are run before coercion.
50
- it { OpenStruct.new(:length=>1).extend(representer).to_hash.must_equal({"length" => 1.1}) }
51
- end
52
- end
@@ -1,135 +0,0 @@
1
- require 'test_helper'
2
-
3
- # tests defining representers in modules, decorators and classes and the inheritance when combined.
4
-
5
- class ConfigInheritTest < MiniTest::Spec
6
- def assert_cloned(child, parent, property)
7
- child_def = child.representable_attrs.get(property)
8
- parent_def = parent.representable_attrs.get(property)
9
-
10
- child_def.merge!(:alias => property)
11
-
12
- child_def[:alias].wont_equal parent_def[:alias]
13
- child_def.object_id.wont_equal parent_def.object_id
14
- end
15
- # class Object
16
-
17
- # end
18
- module GenreModule
19
- include Representable::Hash
20
- property :genre
21
- end
22
-
23
-
24
- # in Decorator ------------------------------------------------
25
- class Decorator < Representable::Decorator
26
- include Representable::Hash
27
- property :title
28
- property :artist do
29
- property :id
30
- end
31
- end
32
-
33
- it { Decorator.definitions.keys.must_equal ["title", "artist"] }
34
-
35
- # in inheriting Decorator
36
-
37
- class InheritingDecorator < Decorator
38
- property :location
39
- end
40
-
41
- it { InheritingDecorator.definitions.keys.must_equal ["title", "artist", "location"] }
42
- it { assert_cloned(InheritingDecorator, Decorator, "title") }
43
- it do
44
- InheritingDecorator.representable_attrs.get(:artist).representer_module.object_id.wont_equal Decorator.representable_attrs.get(:artist).representer_module.object_id
45
- end
46
-
47
- # in inheriting and including Decorator
48
-
49
- class InheritingAndIncludingDecorator < Decorator
50
- include GenreModule
51
- property :location
52
- end
53
-
54
- it { InheritingAndIncludingDecorator.definitions.keys.must_equal ["title", "artist", "genre", "location"] }
55
- it { assert_cloned(InheritingAndIncludingDecorator, GenreModule, :genre) }
56
-
57
-
58
- # in module ---------------------------------------------------
59
- module Module
60
- include Representable
61
- property :title
62
- end
63
-
64
- it { Module.definitions.keys.must_equal ["title"] }
65
-
66
-
67
- # in module including module
68
- module SubModule
69
- include Representable
70
- include Module
71
-
72
- property :location
73
- end
74
-
75
- it { SubModule.definitions.keys.must_equal ["title", "location"] }
76
- it { assert_cloned(SubModule, Module, :title) }
77
-
78
- # including preserves order
79
- module IncludingModule
80
- include Representable
81
- property :genre
82
- include Module
83
-
84
- property :location
85
- end
86
-
87
- it { IncludingModule.definitions.keys.must_equal ["genre", "title", "location"] }
88
-
89
-
90
- # included in class -------------------------------------------
91
- class Class
92
- include Representable
93
- include IncludingModule
94
- end
95
-
96
- it { Class.definitions.keys.must_equal ["genre", "title", "location"] }
97
- it { assert_cloned(Class, IncludingModule, :title) }
98
- it { assert_cloned(Class, IncludingModule, :location) }
99
- it { assert_cloned(Class, IncludingModule, :genre) }
100
-
101
- # included in class with order
102
- class DefiningClass
103
- include Representable
104
- property :street_cred
105
- include IncludingModule
106
- end
107
-
108
- it { DefiningClass.definitions.keys.must_equal ["street_cred", "genre", "title", "location"] }
109
-
110
- # in class
111
- class RepresenterClass
112
- include Representable
113
- property :title
114
- end
115
-
116
- it { RepresenterClass.definitions.keys.must_equal ["title"] }
117
-
118
-
119
- # in inheriting class
120
- class InheritingClass < RepresenterClass
121
- include Representable
122
- property :location
123
- end
124
-
125
- it { InheritingClass.definitions.keys.must_equal ["title", "location"] }
126
- it { assert_cloned(InheritingClass, RepresenterClass, :title) }
127
-
128
- # in inheriting class and including
129
- class InheritingAndIncludingClass < RepresenterClass
130
- property :location
131
- include GenreModule
132
- end
133
-
134
- it { InheritingAndIncludingClass.definitions.keys.must_equal ["title", "location", "genre"] }
135
- end
@@ -1,122 +0,0 @@
1
- require 'test_helper'
2
-
3
- class ConfigTest < MiniTest::Spec
4
- subject { Representable::Config.new(Representable::Definition) }
5
- PunkRock = Class.new
6
- Definition = Representable::Definition
7
-
8
- describe "wrapping" do
9
- it "returns false per default" do
10
- assert_equal nil, subject.wrap_for("Punk", nil)
11
- end
12
-
13
- # it "infers a printable class name if set to true" do
14
- # subject.wrap = true
15
- # assert_equal "punk_rock", subject.wrap_for(PunkRock, nil)
16
- # end
17
-
18
- # it "can be set explicitely" do
19
- # subject.wrap = "Descendents"
20
- # assert_equal "Descendents", subject.wrap_for(PunkRock, nil)
21
- # end
22
- end
23
-
24
- describe "#[]" do
25
- # does return nil for non-existent
26
- it { subject[:hello].must_equal nil }
27
- end
28
-
29
- # describe "#[]" do
30
- # before { subject.add(:title, {:me => true}) }
31
-
32
- # it { subject[:unknown].must_equal nil }
33
- # it { subject.get(:title)[:me].must_equal true }
34
- # it { subject["title"][:me].must_equal true }
35
- # end
36
-
37
- # []=
38
- # []=(... inherit: true)
39
- # forwarded to Config#definitions
40
- # that goes to ConfigDefinitionsTest
41
- describe "#add" do
42
- describe "returns" do
43
- it do
44
- # #add returns Definition.`
45
- subject = Representable::Config.new(Representable::Definition).add(:title, {:me => true})
46
-
47
- subject.must_be_kind_of Representable::Definition
48
- subject[:me].must_equal true
49
- end
50
- end
51
-
52
- before { subject.add(:title, {:me => true}) }
53
-
54
- # must be kind of Definition
55
- it { subject.size.must_equal 1 }
56
- it { subject.get(:title).name.must_equal "title" }
57
- it { subject.get(:title)[:me].must_equal true }
58
-
59
- # this is actually tested in context in inherit_test.
60
- it "overrides former definition" do
61
- subject.add(:title, {:peer => Module})
62
- subject.get(:title)[:me].must_equal nil
63
- subject.get(:title)[:peer].must_equal Module
64
- end
65
-
66
- describe "inherit: true" do
67
- before {
68
- subject.add(:title, {:me => true})
69
- subject.add(:title, {:peer => Module, :inherit => true})
70
- }
71
-
72
- it { subject.get(:title)[:me].must_equal true }
73
- it { subject.get(:title)[:peer].must_equal Module }
74
- end
75
- end
76
-
77
-
78
- describe "#remove" do
79
- subject { Representable::Config.new(Representable::Definition) }
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
-
92
- describe "#each" do
93
- before { subject.add(:title, {:me => true}) }
94
-
95
- it "what" do
96
- definitions = []
97
- subject.each { |dfn| definitions << dfn }
98
- definitions.size.must_equal 1
99
- definitions[0][:me].must_equal true
100
- end
101
- end
102
-
103
- describe "#options" do
104
- it { subject.options.must_equal({}) }
105
- it do
106
- subject.options[:namespacing] = true
107
- subject.options[:namespacing].must_equal true
108
- end
109
- end
110
-
111
- describe "#get" do
112
- subject { Representable::Config.new(Representable::Definition) }
113
-
114
- it do
115
- title = subject.add(:title, {})
116
- length = subject.add(:length, {})
117
-
118
- subject.get(:title).must_equal title
119
- subject.get(:length).must_equal length
120
- end
121
- end
122
- end
@@ -1,28 +0,0 @@
1
- require 'test_helper'
2
-
3
- # TODO: remove in 2.0.
4
- class DecoratorScopeTest < MiniTest::Spec
5
- representer! do
6
- property :title, :getter => lambda { |*| title_from_representer }, :decorator_scope => true
7
- end
8
-
9
- let (:representer_with_method) {
10
- Module.new do
11
- include Representable::Hash
12
- property :title, :decorator_scope => true
13
- def title; "Crystal Planet"; end
14
- end
15
- }
16
-
17
- it "executes lambdas in represented context" do
18
- Class.new do
19
- def title_from_representer
20
- "Sounds Of Silence"
21
- end
22
- end.new.extend(representer).to_hash.must_equal({"title"=>"Sounds Of Silence"})
23
- end
24
-
25
- it "executes method in represented context" do
26
- Object.new.extend(representer_with_method).to_hash.must_equal({"title"=>"Crystal Planet"})
27
- end
28
- end