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,148 +0,0 @@
1
- require 'test_helper'
2
-
3
- # Include Inherit Module And Decorator Test
4
- class SchemaTest < MiniTest::Spec
5
- module Genre
6
- include Representable
7
- property :genre
8
- end
9
-
10
- module LinkFeature
11
- def self.included(base)
12
- base.extend(Link)
13
- end
14
-
15
- module Link
16
- def link
17
- end
18
- end
19
- end
20
-
21
-
22
- module Module
23
- include Representable::Hash
24
- feature LinkFeature
25
-
26
- property :title
27
- property :label do # extend: LabelModule
28
- property :name
29
- link # feature
30
-
31
- property :location do
32
- property :city
33
- link # feature.
34
- end
35
- end
36
-
37
- property :album, :extend => lambda { raise "don't manifest me!" } # this is not an inline decorator, don't manifest it.
38
-
39
-
40
- include Genre # Schema::Included::included is called!
41
- end
42
-
43
-
44
- class WithLocationStreetRepresenter < Representable::Decorator
45
- include Representable::Hash
46
- feature LinkFeature
47
-
48
- property :title
49
- property :label do # extend: LabelModule
50
- property :name
51
- link # feature
52
-
53
- property :location do
54
- property :city
55
- link # feature.
56
- end
57
- end
58
- end
59
-
60
- describe "3-level deep with features" do
61
- let (:label) { OpenStruct.new(:name => "Epitaph", :location => OpenStruct.new(:city => "Sanfran", :name => "DON'T SHOW ME!")) }
62
-
63
- # Module does correctly include features in inlines.
64
- it { band.extend(Module).to_hash.must_equal({"label"=>{"name"=>"Epitaph", "location"=>{"city"=>"Sanfran"}}, "genre"=>"Punkrock"}) }
65
-
66
- # Decorator does correctly include features in inlines.
67
- it { Decorator.new(band).to_hash.must_equal({"label"=>{"name"=>"Epitaph", "location"=>{"city"=>"Sanfran"}}, "genre"=>"Punkrock"}) }
68
- end
69
-
70
-
71
-
72
- class Decorator < Representable::Decorator
73
- feature Representable::Hash
74
-
75
- include Module
76
- end
77
-
78
- # puts Decorator.representable_attrs[:definitions].inspect
79
-
80
- let (:label) { OpenStruct.new(:name => "Fat Wreck", :city => "San Francisco", :employees => [OpenStruct.new(:name => "Mike")], :location => OpenStruct.new(:city => "Sanfran")) }
81
- let (:band) { OpenStruct.new(:genre => "Punkrock", :label => label) }
82
-
83
-
84
- # it { FlatlinersDecorator.new( OpenStruct.new(label: OpenStruct.new) ).
85
- # to_hash.must_equal({}) }
86
- it do
87
- Decorator.new(band).to_hash.must_equal({"genre"=>"Punkrock", "label"=>{"name"=>"Fat Wreck", "location"=>{"city"=>"Sanfran"}}})
88
- end
89
-
90
-
91
- class InheritDecorator < Representable::Decorator
92
- include Representable::Hash
93
-
94
- include Module
95
-
96
- property :label, inherit: true do # decorator.rb:27:in `initialize': superclass must be a Class (Module given)
97
- property :city
98
-
99
- property :location, :inherit => true do
100
- property :city
101
- end
102
- end
103
- end
104
-
105
- it do
106
- InheritDecorator.new(band).to_hash.must_equal({"genre"=>"Punkrock", "label"=>{"name"=>"Fat Wreck", "city"=>"San Francisco", "location"=>{"city"=>"Sanfran"}}})
107
- end
108
-
109
-
110
-
111
- class InheritFromDecorator < InheritDecorator
112
- property :label, inherit: true do
113
- collection :employees do
114
- property :name
115
- end
116
- end
117
- end
118
-
119
- require "pp"
120
- pp InheritFromDecorator.representable_attrs.get(:label)[:extend].(nil).representable_attrs
121
-
122
- it do
123
- InheritFromDecorator.new(band).to_hash.must_equal({"genre"=>"Punkrock", "label"=>{"name"=>"Fat Wreck", "city"=>"San Francisco", "employees"=>[{"name"=>"Mike"}], "location"=>{"city"=>"Sanfran"}}})
124
- end
125
- end
126
-
127
-
128
- class ApplyTest < MiniTest::Spec
129
- class AlbumDecorator < Representable::Decorator
130
- include Representable::Hash
131
-
132
- property :title
133
-
134
- property :hit do
135
- property :title
136
- end
137
-
138
- collection :songs do
139
- property :title
140
- end
141
-
142
- property :band do # yepp, people do crazy stuff like that.
143
- property :label do
144
- property :name
145
- end
146
- end
147
- end
148
- end
@@ -1,33 +0,0 @@
1
- require 'test_helper'
2
-
3
- class SerializeDeserializeTest < BaseTest
4
- subject { Struct.new(:song).new.extend(representer) }
5
-
6
- describe "deserialize" do
7
- representer! do
8
- property :song,
9
- :instance => lambda { |fragment, *| fragment.to_s.upcase },
10
- :prepare => lambda { |fragment, *| fragment },
11
- :deserialize => lambda { |object, fragment, args|
12
- "#{object} #{fragment} #{args.inspect}"
13
- }
14
- end
15
-
16
- it { subject.from_hash({"song" => Object}, {:volume => 9}).song.must_equal "OBJECT Object {:volume=>9}" }
17
- end
18
-
19
- describe "serialize" do
20
- representer! do
21
- property :song,
22
- :representable => true,
23
- :prepare => lambda { |fragment, *| fragment },
24
- :serialize => lambda { |object, args|
25
- "#{object} #{args.inspect}"
26
- }
27
- end
28
-
29
- before { subject.song = "Arrested In Shanghai" }
30
-
31
- it { subject.to_hash({:volume => 9}).must_equal({"song"=>"Arrested In Shanghai {:volume=>9}"}) }
32
- end
33
- end
@@ -1,81 +0,0 @@
1
- require 'test_helper'
2
-
3
- class SkipParseTest < MiniTest::Spec
4
- representer! do
5
- property :title, skip_parse: lambda { |fragment, opts| opts[:skip?] and fragment == "skip me" }
6
- property :band,
7
- skip_parse: lambda { |fragment, opts| opts[:skip?] and fragment["name"].nil? }, class: OpenStruct do
8
- property :name
9
- end
10
-
11
- collection :airplays,
12
- skip_parse: lambda { |fragment, opts| opts[:skip?] and fragment["station"].nil? }, class: OpenStruct do
13
- property :station
14
- end
15
- end
16
-
17
- let (:song) { OpenStruct.new.extend(representer) }
18
-
19
- # do parse.
20
- it do
21
- song.from_hash({
22
- "title" => "Victim Of Fate",
23
- "band" => {"name" => "Mute 98"},
24
- "airplays" => [{"station" => "JJJ"}]
25
- }, skip?: true)
26
-
27
- song.title.must_equal "Victim Of Fate"
28
- song.band.name.must_equal "Mute 98"
29
- song.airplays[0].station.must_equal "JJJ"
30
- end
31
-
32
- # skip parsing.
33
- let (:airplay) { OpenStruct.new(station: "JJJ") }
34
-
35
- it do
36
- song.from_hash({
37
- "title" => "skip me",
38
- "band" => {},
39
- "airplays" => [{"station" => "JJJ"}, {}],
40
- }, skip?: true)
41
-
42
- song.title.must_equal nil
43
- song.band.must_equal nil
44
- song.airplays.must_equal [airplay]
45
- end
46
- end
47
-
48
- class SkipRenderTest < MiniTest::Spec
49
- representer! do
50
- property :title
51
- property :band,
52
- skip_render: lambda { |object, opts| opts[:skip?] and object.name == "Rancid" } do
53
- property :name
54
- end
55
-
56
- collection :airplays,
57
- skip_render: lambda { |object, opts| puts object.inspect; opts[:skip?] and object.station == "Radio Dreyeckland" } do
58
- property :station
59
- end
60
- end
61
-
62
- let (:song) { OpenStruct.new(title: "Black Night", band: OpenStruct.new(name: "Time Again")).extend(representer) }
63
- let (:skip_song) { OpenStruct.new(title: "Time Bomb", band: OpenStruct.new(name: "Rancid")).extend(representer) }
64
-
65
- # do render.
66
- it { song.to_hash(skip?: true).must_equal({"title"=>"Black Night", "band"=>{"name"=>"Time Again"}}) }
67
- # skip.
68
- it { skip_song.to_hash(skip?: true).must_equal({"title"=>"Time Bomb"}) }
69
-
70
- # do render all collection items.
71
- it do
72
- song = OpenStruct.new(airplays: [OpenStruct.new(station: "JJJ"), OpenStruct.new(station: "ABC")]).extend(representer)
73
- song.to_hash(skip?: true).must_equal({"airplays"=>[{"station"=>"JJJ"}, {"station"=>"ABC"}]})
74
- end
75
-
76
- # skip middle item.
77
- it do
78
- song = OpenStruct.new(airplays: [OpenStruct.new(station: "JJJ"), OpenStruct.new(station: "Radio Dreyeckland"), OpenStruct.new(station: "ABC")]).extend(representer)
79
- song.to_hash(skip?: true).must_equal({"airplays"=>[{"station"=>"JJJ"}, {"station"=>"ABC"}]})
80
- end
81
- end
@@ -1,41 +0,0 @@
1
- require 'test_helper'
2
-
3
- class StringifyHashTest < MiniTest::Spec
4
- describe "#from_hash" do
5
- representer!(:name => :song_representer) do
6
-
7
- include Representable::Hash
8
- include Representable::Hash::AllowSymbols
9
-
10
- property :title
11
- end
12
-
13
- representer!(:inject => :song_representer) do
14
- include Representable::Hash::AllowSymbols
15
-
16
- property :song, :extend => song_representer, :class => OpenStruct
17
- end
18
-
19
- it "parses symbols, too" do
20
- OpenStruct.new.extend(representer).from_hash({:song => {:title => "Der Optimist"}}).song.title.must_equal "Der Optimist"
21
- end
22
-
23
- it "still parses strings" do
24
- OpenStruct.new.extend(representer).from_hash({"song" => {"title" => "Der Optimist"}}).song.title.must_equal "Der Optimist"
25
- end
26
-
27
- describe "with :wrap" do
28
- representer!(:inject => :song_representer) do
29
- include Representable::Hash::AllowSymbols
30
-
31
- self.representation_wrap = :album
32
- property :song, :extend => song_representer, :class => OpenStruct
33
- end
34
-
35
- it "parses symbols, too" do
36
- OpenStruct.new.extend(representer).from_hash({:album => {:song => {:title => "Der Optimist"}}}).song.title.must_equal "Der Optimist"
37
- end
38
- end
39
- end
40
-
41
- end
@@ -1,135 +0,0 @@
1
- require 'representable'
2
-
3
- require "json"
4
- require "psych"
5
-
6
- require 'representable/json'
7
- require 'representable/xml'
8
- require 'representable/yaml'
9
- require 'minitest/autorun'
10
- require 'test_xml/mini_test'
11
-
12
- require "representable/debug"
13
-
14
- class Album
15
- attr_accessor :songs, :best_song
16
- def initialize(songs=nil, best_song=nil)
17
- @songs = songs
18
- @best_song = best_song
19
- end
20
-
21
- def ==(other)
22
- songs == other.songs and best_song == other.best_song
23
- end
24
- end
25
-
26
- class Song
27
- attr_accessor :name, :track # never change this, track rendered with Rails#to_json.
28
- def initialize(name=nil, track=nil)
29
- @name = name
30
- @track = track
31
- end
32
-
33
- def ==(other)
34
- name == other.name and track == other.track
35
- end
36
- end
37
-
38
- module XmlHelper
39
- def xml(document)
40
- Nokogiri::XML(document).root
41
- end
42
- end
43
-
44
- module AssertJson
45
- module Assertions
46
- def assert_json(expected, actual, msg=nil)
47
- msg = message(msg, "") { diff expected, actual }
48
- assert(expected.split("").sort == actual.split("").sort, msg)
49
- end
50
- end
51
- end
52
-
53
- MiniTest::Spec.class_eval do
54
- include AssertJson::Assertions
55
- include XmlHelper
56
-
57
- def self.for_formats(formats)
58
- formats.each do |format, cfg|
59
- mod, output, input = cfg
60
- yield format, mod, output, input
61
- end
62
- end
63
-
64
- def render(object, *args)
65
- AssertableDocument.new(object.send("to_#{format}", *args), format)
66
- end
67
-
68
- def parse(object, input, *args)
69
- object.send("from_#{format}", input, *args)
70
- end
71
-
72
- class AssertableDocument
73
- attr_reader :document
74
-
75
- def initialize(document, format)
76
- @document, @format = document, format
77
- end
78
-
79
- def must_equal_document(*args)
80
- return document.must_equal_xml(*args) if @format == :xml
81
- document.must_equal(*args)
82
- end
83
- end
84
-
85
- def self.representer!(options={}, &block)
86
- fmt = options # we need that so the 2nd call to ::let (within a ::describe) remembers the right format.
87
-
88
- name = options[:name] || :representer
89
- format = options[:module] || Representable::Hash
90
-
91
- let(name) do
92
- mod = options[:decorator] ? Class.new(Representable::Decorator) : Module.new
93
-
94
- inject_representer(mod, fmt)
95
-
96
- mod.module_eval do
97
- include format
98
- instance_exec(&block)
99
- end
100
-
101
- mod
102
- end
103
-
104
- def inject_representer(mod, options)
105
- return unless options[:inject]
106
-
107
- injected_name = options[:inject]
108
- injected = send(injected_name) # song_representer
109
- mod.singleton_class.instance_eval do
110
- define_method(injected_name) { injected }
111
- end
112
- end
113
- end
114
-
115
- module TestMethods
116
- def representer_for(modules=[Representable::Hash], &block)
117
- Module.new do
118
- extend TestMethods
119
- include *modules
120
- module_exec(&block)
121
- end
122
- end
123
-
124
- alias_method :representer!, :representer_for
125
- end
126
- include TestMethods
127
- end
128
-
129
- class BaseTest < MiniTest::Spec
130
- let (:new_album) { OpenStruct.new.extend(representer) }
131
- let (:album) { OpenStruct.new(:songs => ["Fuck Armageddon"]).extend(representer) }
132
- let (:song) { OpenStruct.new(:title => "Resist Stance") }
133
- let (:song_representer) { Module.new do include Representable::Hash; property :title end }
134
-
135
- end
@@ -1,25 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestHelperTest < MiniTest::Spec
4
- describe "#assert_json" do
5
- it "tests for equality" do
6
- assert_json "{\"songs\":{\"one\":\"65\",\"two\":\"Emo Boy\"}}", "{\"songs\":{\"one\":\"65\",\"two\":\"Emo Boy\"}}"
7
- end
8
-
9
- it "allows different key orders" do
10
- assert_json "{\"songs\":{\"one\":\"65\",\"two\":\"Emo Boy\"}}", "{\"songs\":{\"two\":\"Emo Boy\",\"one\":\"65\"}}"
11
- end
12
-
13
- it "complains when expected hash is subset" do
14
- assert_raises MiniTest::Assertion do
15
- assert_json "{\"songs\":{\"one\":\"65\"}}", "{\"songs\":{\"two\":\"Emo Boy\",\"one\":\"65\"}}"
16
- end
17
- end
18
-
19
- it "complains when source hash is subset" do
20
- assert_raises MiniTest::Assertion do
21
- assert_json "{\"songs\":{\"two\":\"Emo Boy\",\"one\":\"65\"}}", "{\"songs\":{\"one\":\"65\"}}"
22
- end
23
- end
24
- end
25
- end