representable 2.4.0.rc3 → 2.4.0.rc4

Sign up to get free protection for your applications and to get access to all the features.
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