representable 2.4.0.rc3 → 2.4.0.rc4

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 (99) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +7 -2
  3. data/Rakefile +6 -0
  4. data/lib/representable.rb +21 -17
  5. data/lib/representable/binding.rb +3 -2
  6. data/lib/representable/definition.rb +1 -1
  7. data/lib/representable/deprecations.rb +31 -5
  8. data/lib/representable/deserializer.rb +24 -34
  9. data/lib/representable/hash/collection.rb +9 -2
  10. data/lib/representable/hash_methods.rb +2 -2
  11. data/lib/representable/parse_strategies.rb +6 -7
  12. data/lib/representable/pipeline.rb +12 -1
  13. data/lib/representable/pipeline_factories.rb +9 -2
  14. data/lib/representable/serializer.rb +3 -3
  15. data/lib/representable/version.rb +1 -1
  16. data/test-with-deprecations/as_test.rb +65 -0
  17. data/test-with-deprecations/benchmarking.rb +83 -0
  18. data/test-with-deprecations/binding_test.rb +46 -0
  19. data/test-with-deprecations/blaaaaaaaa_test.rb +69 -0
  20. data/test-with-deprecations/cached_test.rb +147 -0
  21. data/test-with-deprecations/class_test.rb +119 -0
  22. data/test-with-deprecations/coercion_test.rb +52 -0
  23. data/test-with-deprecations/config/inherit_test.rb +135 -0
  24. data/test-with-deprecations/config_test.rb +122 -0
  25. data/test-with-deprecations/decorator_scope_test.rb +28 -0
  26. data/test-with-deprecations/decorator_test.rb +96 -0
  27. data/test-with-deprecations/default_test.rb +34 -0
  28. data/test-with-deprecations/defaults_options_test.rb +93 -0
  29. data/test-with-deprecations/definition_test.rb +264 -0
  30. data/test-with-deprecations/example.rb +310 -0
  31. data/test-with-deprecations/examples/object.rb +31 -0
  32. data/test-with-deprecations/exec_context_test.rb +93 -0
  33. data/test-with-deprecations/features_test.rb +70 -0
  34. data/test-with-deprecations/filter_test.rb +57 -0
  35. data/test-with-deprecations/for_collection_test.rb +74 -0
  36. data/test-with-deprecations/generic_test.rb +116 -0
  37. data/test-with-deprecations/getter_setter_test.rb +21 -0
  38. data/test-with-deprecations/hash_bindings_test.rb +87 -0
  39. data/test-with-deprecations/hash_test.rb +160 -0
  40. data/test-with-deprecations/heritage_test.rb +62 -0
  41. data/test-with-deprecations/if_test.rb +79 -0
  42. data/test-with-deprecations/include_exclude_test.rb +88 -0
  43. data/test-with-deprecations/inherit_test.rb +159 -0
  44. data/test-with-deprecations/inline_test.rb +272 -0
  45. data/test-with-deprecations/instance_test.rb +266 -0
  46. data/test-with-deprecations/is_representable_test.rb +77 -0
  47. data/test-with-deprecations/json_test.rb +355 -0
  48. data/test-with-deprecations/lonely_test.rb +239 -0
  49. data/test-with-deprecations/mongoid_test.rb +31 -0
  50. data/test-with-deprecations/nested_test.rb +115 -0
  51. data/test-with-deprecations/object_test.rb +60 -0
  52. data/{test/---deserialize-pipeline_test.rb → test-with-deprecations/parse_pipeline_test.rb} +29 -2
  53. data/test-with-deprecations/parse_strategy_test.rb +279 -0
  54. data/{test → test-with-deprecations}/pass_options_test.rb +0 -0
  55. data/test-with-deprecations/pipeline_test.rb +277 -0
  56. data/test-with-deprecations/populator_test.rb +105 -0
  57. data/test-with-deprecations/prepare_test.rb +67 -0
  58. data/test-with-deprecations/private_options_test.rb +18 -0
  59. data/test-with-deprecations/reader_writer_test.rb +19 -0
  60. data/test-with-deprecations/realistic_benchmark.rb +115 -0
  61. data/test-with-deprecations/render_nil_test.rb +21 -0
  62. data/test-with-deprecations/represent_test.rb +88 -0
  63. data/test-with-deprecations/representable_test.rb +511 -0
  64. data/test-with-deprecations/schema_test.rb +148 -0
  65. data/test-with-deprecations/serialize_deserialize_test.rb +33 -0
  66. data/test-with-deprecations/skip_test.rb +81 -0
  67. data/test-with-deprecations/stringify_hash_test.rb +41 -0
  68. data/test-with-deprecations/test_helper.rb +135 -0
  69. data/test-with-deprecations/test_helper_test.rb +25 -0
  70. data/test-with-deprecations/uncategorized_test.rb +67 -0
  71. data/test-with-deprecations/user_options_test.rb +15 -0
  72. data/test-with-deprecations/wrap_test.rb +152 -0
  73. data/test-with-deprecations/xml_bindings_test.rb +62 -0
  74. data/test-with-deprecations/xml_test.rb +503 -0
  75. data/test-with-deprecations/yaml_test.rb +162 -0
  76. data/test/as_test.rb +3 -3
  77. data/test/cached_test.rb +2 -2
  78. data/test/class_test.rb +5 -5
  79. data/test/exec_context_test.rb +2 -2
  80. data/test/filter_test.rb +1 -1
  81. data/test/getter_setter_test.rb +4 -4
  82. data/test/if_test.rb +2 -2
  83. data/test/include_exclude_test.rb +88 -0
  84. data/test/instance_test.rb +15 -15
  85. data/test/lonely_test.rb +18 -2
  86. data/test/object_test.rb +4 -4
  87. data/test/parse_pipeline_test.rb +64 -0
  88. data/test/parse_strategy_test.rb +3 -3
  89. data/test/pipeline_test.rb +8 -12
  90. data/test/prepare_test.rb +2 -3
  91. data/test/reader_writer_test.rb +3 -3
  92. data/test/representable_test.rb +12 -48
  93. data/test/serialize_deserialize_test.rb +9 -9
  94. data/test/skip_test.rb +11 -11
  95. data/test/test_helper.rb +2 -0
  96. data/test/uncategorized_test.rb +10 -10
  97. data/test/user_options_test.rb +15 -0
  98. data/test/wrap_test.rb +1 -1
  99. metadata +65 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7f9cc279171577dec367b7910ae42b4d4f8b6240
4
- data.tar.gz: 193116e06652a35c3fa5bd5124a401d51c8d5c7e
3
+ metadata.gz: 37e722a1246b50c21ee87fe22a3a712bc03c3ea0
4
+ data.tar.gz: 4c7cdfbdeb505aaff4f6295ef2b3c717cf4667e4
5
5
  SHA512:
6
- metadata.gz: 14296a6fb55202f2c747cbe0a77e97a3bef8f82673eae9467cd290243dd0ed438f3ffe5fbbf7ec53728818b91459774f18e7141117d9788bd497218ad4899325
7
- data.tar.gz: 35a26662c16e844cb9944cdf06cb9a5014c266f53568e714d0f37e49922076cc200e1126fb554dc13a2a0115a97479ea5ddce300bf3d6663148f9adf9ef108c8
6
+ metadata.gz: c64248b241a38e218d0078116f3fbd3ba79591ca6d9cbed24c80eaa0903c0b017aa5cd18dd1a7bc70f76ee26bf7a2b29b2b6b4c764579762be6a10181555f99a
7
+ data.tar.gz: a3a01d1dcd3ca21b5a2796eb4ad49f708b4d21d9710c160e176465710c45544b2894512322420e295c4dd6a70c8321d9d71814f8a8d448b977912fc99f17c895
data/CHANGES.md CHANGED
@@ -44,13 +44,18 @@ and it suddenly is super simple to understand
44
44
  * Removed `Binding@represented` (which was never public anyway). Use `Binding#represented`.
45
45
  * Changed signature: `Binding#get(represented:)`. In now needs a hash `{represented: ..}`.
46
46
 
47
+ # 2.4.0.rc4
48
+
49
+ * The preferred way of passing user options is now `to_hash(user_options: {})`.
50
+ * Supports nested options for nested representers.
51
+
47
52
  # 2.4.0.rc3
48
53
 
54
+ * `Set` is `SetValue`. `Get` is `GetValue`.
49
55
  * `CreateObject` no longer invokes `AssignFragment`. This is now part of the official parse pipeline.
50
56
 
51
- # 2.4.0.rc4
57
+ # 2.4.0.rc2
52
58
 
53
- * `Set` is `SetValue`. `Get` is `GetValue`.
54
59
  * Use Declarative's `::build_definition` interface instead of overwriting `::property`.
55
60
 
56
61
  # 2.3.0
data/Rakefile CHANGED
@@ -9,3 +9,9 @@ Rake::TestTask.new(:test) do |test|
9
9
  test.test_files = FileList['test/**/*_test.rb']
10
10
  test.verbose = true
11
11
  end
12
+
13
+ Rake::TestTask.new(:dtest) do |test|
14
+ test.libs << 'test-with-deprecations'
15
+ test.test_files = FileList['test-with-deprecations/**/*_test.rb']
16
+ test.verbose = true
17
+ end
data/lib/representable.rb CHANGED
@@ -39,7 +39,7 @@ private
39
39
 
40
40
  # Compiles the document going through all properties.
41
41
  def create_representation_with(doc, options, format)
42
- propagated_options = normalize_options(options) # {_private: {include: }, is_admin: true}
42
+ propagated_options = normalize_options(options)
43
43
 
44
44
  representable_map!(doc, propagated_options, format, :compile_fragment)
45
45
  doc
@@ -63,8 +63,8 @@ private
63
63
  Binding::Map.new(representable_bindings_for(format, options))
64
64
  end
65
65
 
66
- def representable_map!(doc, propagated_options, format, method)
67
- options = {doc: doc, _private: propagated_options[:_private], user_options: propagated_options, represented: represented, decorator: self}
66
+ def representable_map!(doc, options, format, method)
67
+ options = {doc: doc, options: options, represented: represented, decorator: self}
68
68
 
69
69
  representable_map(options, format).(method, options) # .(:uncompile_fragment, options)
70
70
  end
@@ -73,23 +73,24 @@ private
73
73
  representable_attrs.collect {|definition| format.build(definition) }
74
74
  end
75
75
 
76
- # Make sure we do not change original options. However, private options like :include or :wrap are
77
- # not passed on to child representers.
78
- def normalize_options(options)
79
- # here, we could also filter out local options e.g. like options[:band].
80
- return options unless options.any?
81
-
82
- propagated_options = options.dup
83
- propagated_options.delete(:wrap) # FIXME.
84
- propagated_options.delete(:_private)
76
+ module NormalizeOptions
77
+ def normalize_options(options)
78
+ return options if options.any?
79
+ {user_options: {}}.merge(options) # TODO: use keyword args once we drop 2.0.
80
+ end
81
+ end
85
82
 
86
- private_options = {}
87
- private_options[:include] = propagated_options.delete(:include) if options[:include]
88
- private_options[:exclude] = propagated_options.delete(:exclude) if options[:exclude]
83
+ # Prepares options for a particular nested representer.
84
+ # This is used in Serializer and Deserializer.
85
+ OptionsForNested = ->(options, binding) do
86
+ child_options = {user_options: options[:user_options], }
89
87
 
90
- propagated_options[:_private] = private_options if private_options.any?
88
+ # wrap:
89
+ child_options[:wrap] = binding[:wrap] unless binding[:wrap].nil?
91
90
 
92
- propagated_options
91
+ # nested params:
92
+ child_options.merge!(options[binding.name.to_sym]) if options[binding.name.to_sym]
93
+ child_options
93
94
  end
94
95
 
95
96
  def representable_attrs
@@ -123,6 +124,9 @@ private
123
124
  def self.deprecations=(value)
124
125
  evaluator = value==false ? Binding::EvaluateOption : Binding::Deprecation::EvaluateOption
125
126
  ::Representable::Binding.send :include, evaluator
127
+
128
+ evaluator = value==false ? NormalizeOptions : Deprecation::NormalizeOptions
129
+ ::Representable.send :include, evaluator
126
130
  end
127
131
  self.deprecations = true # TODO: change to false in 2.5 or remove entirely.
128
132
  end
@@ -41,9 +41,10 @@ module Representable
41
41
  include Deprecatable
42
42
 
43
43
  module EvaluateOption
44
- def evaluate_option(name, input=nil, options={})
44
+ def evaluate_option(name, input, options)
45
45
  proc = self[name]
46
- proc.(send(:exec_context, options), options) # from Uber::Options::Value. # NOTE: this can also be the Proc object if it's not wrapped by Uber:::Value.
46
+ # puts "@@@@@ #{self.inspect}, #{name}...... #{self[name]}"
47
+ proc.(send(:exec_context, options), options.merge(user_options: options[:options][:user_options], input: input)) # from Uber::Options::Value. # NOTE: this can also be the Proc object if it's not wrapped by Uber:::Value.
47
48
  end
48
49
  end
49
50
  # include EvaluateOption
@@ -48,7 +48,7 @@ module Representable
48
48
  :"#{name}="
49
49
  end
50
50
 
51
- def typed?
51
+ def typed? # TODO: remove.
52
52
  self[:class] or self[:extend] or self[:instance]
53
53
  end
54
54
 
@@ -1,4 +1,29 @@
1
1
  # WARNING: this will be removed in 3.0.
2
+ module Representable::Deprecation
3
+ module NormalizeOptions
4
+ def normalize_options(options)
5
+
6
+ unless options.any?
7
+ options[:user_options] = {}
8
+ return options
9
+ end
10
+
11
+ options = options.dup
12
+
13
+ user_option_keys = options.keys - [:exclude, :include, :wrap, :user_options, * representable_attrs.keys.map(&:to_sym)]
14
+ if user_option_keys.any?
15
+ user_options = {}
16
+ warn "[Representable] Mixing user and representable options is deprecated. Please provide your options via :user_options."
17
+ user_option_keys.each { |key| user_options[key] = options.delete(key) }
18
+
19
+ options[:user_options] = user_options
20
+ end
21
+
22
+ options # {user_options: {..}, include: [], wrap: "song", artist: {..}}
23
+ end
24
+ end
25
+ end
26
+
2
27
  module Representable::Binding::Deprecation
3
28
  Options = Struct.new(:binding, :user_options, :represented, :decorator)
4
29
 
@@ -32,12 +57,14 @@ module Representable::Binding::Deprecation
32
57
  __options = if self[:pass_options]
33
58
  warn %{[Representable] The :pass_options option is deprecated. Please access environment objects via options[:binding].
34
59
  Learn more here: http://trailblazerb.org/gems/representable/upgrading-guide.html#pass-options}
35
- Options.new(self, options[:user_options], options[:represented], options[:decorator])
60
+
61
+
62
+ options[:options] ||= {}
63
+ Options.new(self, options[:options][:user_options], options[:represented], options[:decorator])
36
64
  else
37
65
  # user_options
38
- options[:user_options]
66
+ options[:options][:user_options] || {}
39
67
  end
40
- # options[:user_options] = __options # TODO: always make this user_options in Representable 3.0.
41
68
 
42
69
  if proc.send(:proc?) or proc.send(:method?)
43
70
  arity = proc.instance_variable_get(:@value).arity if proc.send(:proc?)
@@ -54,12 +81,11 @@ module Representable::Binding::Deprecation
54
81
  deprecated_args << __options and next if arg == :user_options# either hash or Options object.
55
82
  deprecated_args << options[arg]
56
83
  end
57
-
58
84
  return proc.(send(:exec_context, options), *deprecated_args)
59
85
  end
60
86
  end
61
87
 
62
- proc.(send(:exec_context, options), options)
88
+ proc.(send(:exec_context, options), options.merge(user_options: options[:options][:user_options]))
63
89
  end
64
90
  private :evaluate_option_with_deprecation
65
91
 
@@ -31,31 +31,7 @@ module Representable
31
31
  options[:binding].evaluate_option(:skip_parse, input, options) ? Pipeline::Stop : input
32
32
  end
33
33
 
34
- Instance = ->(input, options) do
35
- options[:binding].evaluate_option(:instance, input, options)
36
- end
37
-
38
34
  module Function
39
- class CreateObject
40
- def call(input, options)
41
- instance_for(input, options) || class_for(input, options)
42
- end
43
-
44
- private
45
- def class_for(input, options)
46
- item_class = class_from(input, options) or raise DeserializeError.new(":class did not return class constant for `#{options[:binding].name}`.")
47
- item_class.new
48
- end
49
-
50
- def class_from(input, options)
51
- options[:binding].evaluate_option(:class, input, options) # FIXME: no additional args passed here, yet.
52
- end
53
-
54
- def instance_for(input, options)
55
- Instance.(input, options)
56
- end
57
- end
58
-
59
35
  class Prepare
60
36
  def call(input, options)
61
37
  binding = options[:binding]
@@ -81,16 +57,30 @@ module Representable
81
57
  end
82
58
  end
83
59
 
84
- CreateObject = Function::CreateObject.new
60
+ module CreateObject
61
+ Instance = ->(input, options) { options[:binding].evaluate_option(:instance, input, options)||
62
+ raise( DeserializeError.new(":instance did not return class constant for `#{options[:binding].name}`.")) }
63
+ Class = ->(input, options) do
64
+ object_class = options[:binding].evaluate_option(:class, input, options) ||
65
+ raise( DeserializeError.new(":class did not return class constant for `#{options[:binding].name}`."))
66
+ object_class.new
67
+ end # FIXME: no additional args passed here, yet.
68
+
69
+ Populator = ->(*) { raise "Populator: implement me!" }
70
+ end
71
+
72
+ # CreateObject = Function::CreateObject.new
85
73
  Prepare = Function::Prepare.new
86
74
  Decorate = Function::Decorate.new
87
- Deserializer = ->(input, options) { options[:binding].evaluate_option(:deserialize, input, options) }
75
+ Deserializer = ->(input, options) { options[:binding].evaluate_option(:deserialize, input, options) }
76
+
77
+ Deserialize = ->(input, args) do
78
+ binding, fragment, options = args[:binding], args[:fragment], args[:options]
88
79
 
89
- Deserialize = ->(input, options) do
90
- binding, fragment, user_options = options[:binding], options[:fragment], options[:user_options]
80
+ # user_options:
81
+ child_options = OptionsForNested.(options, args[:binding])
91
82
 
92
- user_options = user_options.merge(wrap: binding[:wrap]) unless binding[:wrap].nil? # DISCUSS: can we leave that here?
93
- input.send(binding.deserialize_method, fragment, user_options)
83
+ input.send(binding.deserialize_method, fragment, child_options)
94
84
  end
95
85
 
96
86
  ParseFilter = ->(input, options) do
@@ -106,13 +96,13 @@ module Representable
106
96
  If = ->(input, options) { options[:binding].evaluate_option(:if, nil, options) ? input : Pipeline::Stop }
107
97
 
108
98
  StopOnExcluded = ->(input, options) do
109
- return input unless private = options[:_private]
110
- return input unless props = (private[:exclude] || private[:include])
99
+ return input unless private = options[:options]
100
+ return input unless props = (options[:options][:exclude] || options[:options][:include])
111
101
 
112
102
  res = props.include?(options[:binding].name.to_sym) # false with include: Stop. false with exclude: go!
113
103
 
114
- return input if private[:include]&&res
115
- return input if private[:exclude]&&!res
104
+ return input if options[:options][:include]&&res
105
+ return input if options[:options][:exclude]&&!res
116
106
  Pipeline::Stop
117
107
  end
118
108
  end
@@ -17,19 +17,26 @@ module Representable::Hash
17
17
  end
18
18
  end
19
19
 
20
+ # TODO: revise lonely collection and build separate pipeline where we just use Serialize, etc.
20
21
 
21
22
  def create_representation_with(doc, options, format)
23
+ options = normalize_options(options)
24
+ options[:_self] = options
25
+
22
26
  bin = representable_bindings_for(format, options).first
23
27
 
24
28
  Collect[*bin.default_render_fragment_functions].
25
- (represented, {doc: doc, fragment: represented, user_options: options, binding: bin, represented: represented})
29
+ (represented, {doc: doc, fragment: represented, options: options, binding: bin, represented: represented})
26
30
  end
27
31
 
28
32
  def update_properties_from(doc, options, format)
33
+ options = normalize_options(options)
34
+ options[:_self] = options
35
+
29
36
  bin = representable_bindings_for(format, options).first
30
37
 
31
38
  value = Collect[*bin.default_parse_fragment_functions].
32
- (doc, fragment: doc, document: doc, user_options: options, binding: bin, represented: represented)
39
+ (doc, fragment: doc, document: doc, options: options, binding: bin, represented: represented)
33
40
 
34
41
  represented.replace(value)
35
42
  end
@@ -4,14 +4,14 @@ module Representable
4
4
  hash = filter_keys_for!(represented, options) # FIXME: this modifies options and replicates logic from Representable.
5
5
  bin = representable_map(options, format).first
6
6
 
7
- Collect::Hash[*bin.default_render_fragment_functions].(hash, {doc: doc, user_options: options, binding: bin, represented: represented, decorator: self})
7
+ Collect::Hash[*bin.default_render_fragment_functions].(hash, {doc: doc, options: options, binding: bin, represented: represented, decorator: self})
8
8
  end
9
9
 
10
10
  def update_properties_from(doc, options, format)
11
11
  hash = filter_keys_for!(doc, options)
12
12
  bin = representable_map(options, format).first
13
13
 
14
- value = Collect::Hash[*bin.default_parse_fragment_functions].(hash, fragment: hash, document: doc, binding: bin, represented: represented, user_options: options, decorator: self)
14
+ value = Collect::Hash[*bin.default_parse_fragment_functions].(hash, fragment: hash, document: doc, binding: bin, represented: represented, options: options, decorator: self)
15
15
 
16
16
  represented.replace(value)
17
17
  end
@@ -24,7 +24,7 @@ module Representable
24
24
  options[:parse_pipeline] = ->(input, options) do
25
25
  pipeline = Pipeline[*parse_functions] # TODO: AssignFragment
26
26
  pipeline = Pipeline::Insert.(pipeline, SetValue, delete: true) # remove the setter function.
27
- pipeline = Pipeline::Insert.(pipeline, populator, replace: CreateObject) # let the populator do CreateObject's job.
27
+ pipeline = Pipeline::Insert.(pipeline, populator, replace: CreateObject::Populator) # let the actual populator do the job.
28
28
  # puts pipeline.extend(Representable::Pipeline::Debug).inspect
29
29
  pipeline
30
30
  end
@@ -72,8 +72,8 @@ module Representable
72
72
  options[:setter] = lambda { |*args| }
73
73
  options[:pass_options] = true
74
74
  options[:instance] = options[:collection] ?
75
- lambda { |fragment, i, options| options.binding.get(represented: options.represented)[i] } :
76
- lambda { |fragment, options| options.binding.get(represented: options.represented) }
75
+ lambda { |options| options[:binding].get(options)[options[:index]] } :
76
+ lambda { |options| options[:binding].get(options) }
77
77
  end
78
78
  end
79
79
 
@@ -82,11 +82,10 @@ module Representable
82
82
  class FindOrInstantiate
83
83
  def self.apply!(name, options)
84
84
  options[:pass_options] = true
85
- options[:instance] = lambda { |fragment, *args|
86
- args = args.last # TODO: don't pass i as separate block parameter but in Options.
87
- object_class = args.binding[:class].evaluate(self, fragment, args)
85
+ options[:instance] = lambda { |options|
86
+ object_class = options[:binding][:class].evaluate(self, options)
88
87
 
89
- object_class.find_by({id: fragment["id"]}) or object_class.new
88
+ object_class.find_by({id: options[:fragment]["id"]}) or object_class.new
90
89
  }
91
90
  end
92
91
  end
@@ -19,7 +19,18 @@ module Representable
19
19
  def evaluate(block, input, options)
20
20
  block.call(input, options)
21
21
  end
22
- end
22
+
23
+
24
+ module Insert # TODO: explicit test.
25
+ # Macro to quickly modify an array of functions via Pipeline::Insert and return a
26
+ # Pipeline instance.
27
+ def insert(functions, new_function, options)
28
+ Pipeline.new(Insert.(functions, new_function, options))
29
+
30
+ end
31
+ end
32
+ extend Insert
33
+ end # Pipeline
23
34
 
24
35
 
25
36
  # Collect applies a pipeline to each element of input.
@@ -67,8 +67,15 @@ module Representable
67
67
  functions = [AssignFragment]
68
68
  functions << SkipParse if self[:skip_parse]
69
69
 
70
- if typed?
71
- functions << CreateObject
70
+ if self[:class] or self[:extend] or self[:instance] or self[:populator]
71
+ if self[:populator]
72
+ functions << CreateObject::Populator
73
+ elsif self[:parse_strategy]
74
+ functions << CreateObject::Instance # TODO: remove in 2.5.
75
+ else
76
+ functions << (self[:class] ? CreateObject::Class : CreateObject::Instance)
77
+ end
78
+
72
79
  functions << Prepare if self[:prepare]
73
80
  functions << Decorate if self[:extend]
74
81
  if representable?
@@ -37,11 +37,11 @@ module Representable
37
37
 
38
38
  Serialize = ->(input, options) do
39
39
  return if input.nil? # DISCUSS: how can we prevent that?
40
- binding, user_options = options[:binding], options[:user_options]
40
+ binding, options = options[:binding], options[:options] # FIXME: rename to :local_options.
41
41
 
42
- user_options = user_options.merge(wrap: binding[:wrap]) unless binding[:wrap].nil? # DISCUSS: can we leave that here?
42
+ options_for_nested = OptionsForNested.(options, binding)
43
43
 
44
- input.send(binding.serialize_method, user_options)
44
+ input.send(binding.serialize_method, options_for_nested)
45
45
  end
46
46
 
47
47
  WriteFragment = ->(input, options) { options[:binding].write(options[:doc], input, options[:as]) }
@@ -1,3 +1,3 @@
1
1
  module Representable
2
- VERSION = "2.4.0.rc3"
2
+ VERSION = "2.4.0.rc4"
3
3
  end
@@ -0,0 +1,65 @@
1
+ require 'test_helper'
2
+
3
+ class AsTest < MiniTest::Spec
4
+ for_formats(
5
+ :hash => [Representable::Hash, {"title" => "Wie Es Geht"}, {"title" => "Revolution"}],
6
+ # :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>"],
7
+ # :yaml => [Representable::YAML, "---\nsong:\n name: Alive\n", "---\nsong:\n name: You've Taken Everything\n"],
8
+ ) do |format, mod, input, output|
9
+
10
+ let (:song) { representer.prepare(Song.new("Revolution")) }
11
+ let (:format) { format }
12
+
13
+
14
+ describe "as: with :symbol" do
15
+ representer!(:module => mod) do
16
+ property :name, :as => :title
17
+ end
18
+
19
+ it { render(song).must_equal_document output }
20
+ it { parse(song, input).name.must_equal "Wie Es Geht" }
21
+ end
22
+
23
+
24
+ describe "as: with lambda" do
25
+ representer!(:module => mod) do
26
+ property :name, :as => lambda { |*| "#{self.class}" }
27
+ end
28
+
29
+ it { render(song).must_equal_document({"Song" => "Revolution"}) }
30
+ it { parse(song, {"Song" => "Wie Es Geht"}).name.must_equal "Wie Es Geht" }
31
+ end
32
+
33
+
34
+ describe "lambda arguments" do
35
+ representer! do
36
+ property :name, :as => lambda { |*args| args.inspect }
37
+ end
38
+
39
+ it { render(song, :volume => 1).must_equal_document({"[{:volume=>1}]" => "Revolution"}) }
40
+ it { parse(song, {"[{:volume=>1}]" => "Wie Es Geht"}, :volume => 1).name.must_equal "Wie Es Geht" }
41
+ end
42
+ end
43
+ end
44
+
45
+
46
+ # hash: to_hash(wrap: ) is representation_wrap
47
+
48
+ class AsXmlTest < MiniTest::Spec
49
+ Band = Struct.new(:name, :label)
50
+ Album = Struct.new(:band)
51
+ Label = Struct.new(:name)
52
+
53
+ representer!(module: Representable::XML, decorator: true) do
54
+ self.representation_wrap = :album
55
+ property :band, as: :combo do
56
+ self.representation_wrap = :band
57
+ property :name
58
+ end
59
+ end
60
+
61
+ it do
62
+ skip
63
+ representer.new(Album.new(Band.new("Offspring"))).to_xml.must_equal ""
64
+ end
65
+ end