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,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