representable 3.0.4 → 3.2.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 (96) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +23 -0
  3. data/CHANGES.md +14 -0
  4. data/Gemfile +4 -7
  5. data/LICENSE +1 -1
  6. data/README.md +12 -12
  7. data/Rakefile +1 -6
  8. data/lib/representable/binding.rb +32 -12
  9. data/lib/representable/cached.rb +1 -1
  10. data/lib/representable/coercion.rb +8 -6
  11. data/lib/representable/config.rb +8 -3
  12. data/lib/representable/debug.rb +23 -15
  13. data/lib/representable/declarative.rb +8 -3
  14. data/lib/representable/decorator.rb +1 -1
  15. data/lib/representable/definition.rb +7 -2
  16. data/lib/representable/deserializer.rb +4 -3
  17. data/lib/representable/for_collection.rb +1 -1
  18. data/lib/representable/hash/allow_symbols.rb +9 -11
  19. data/lib/representable/hash/binding.rb +1 -0
  20. data/lib/representable/hash/collection.rb +4 -2
  21. data/lib/representable/hash.rb +6 -2
  22. data/lib/representable/hash_methods.rb +3 -2
  23. data/lib/representable/insert.rb +1 -1
  24. data/lib/representable/json/collection.rb +3 -0
  25. data/lib/representable/json/hash.rb +1 -0
  26. data/lib/representable/json.rb +5 -7
  27. data/lib/representable/object/binding.rb +5 -1
  28. data/lib/representable/object.rb +1 -1
  29. data/lib/representable/option.rb +19 -0
  30. data/lib/representable/pipeline.rb +3 -2
  31. data/lib/representable/pipeline_factories.rb +4 -2
  32. data/lib/representable/populator.rb +1 -1
  33. data/lib/representable/represent.rb +1 -0
  34. data/lib/representable/serializer.rb +2 -1
  35. data/lib/representable/version.rb +1 -1
  36. data/lib/representable/xml/binding.rb +5 -6
  37. data/lib/representable/xml.rb +7 -10
  38. data/lib/representable/yaml/binding.rb +1 -0
  39. data/lib/representable/yaml.rb +3 -3
  40. data/lib/representable.rb +18 -25
  41. data/representable.gemspec +3 -3
  42. data/test/as_test.rb +4 -4
  43. data/test/binding_test.rb +10 -10
  44. data/test/cached_test.rb +19 -19
  45. data/test/class_test.rb +7 -7
  46. data/test/coercion_test.rb +33 -22
  47. data/test/config/inherit_test.rb +14 -14
  48. data/test/config_test.rb +18 -18
  49. data/test/decorator_scope_test.rb +3 -3
  50. data/test/decorator_test.rb +17 -17
  51. data/test/default_test.rb +7 -7
  52. data/test/definition_test.rb +32 -32
  53. data/test/{example.rb → examples/example.rb} +0 -0
  54. data/test/exec_context_test.rb +6 -6
  55. data/test/features_test.rb +3 -3
  56. data/test/filter_test.rb +6 -6
  57. data/test/for_collection_test.rb +2 -2
  58. data/test/generic_test.rb +3 -3
  59. data/test/getter_setter_test.rb +5 -5
  60. data/test/hash_test.rb +19 -19
  61. data/test/heritage_test.rb +4 -4
  62. data/test/if_test.rb +6 -6
  63. data/test/include_exclude_test.rb +12 -12
  64. data/test/inherit_test.rb +15 -15
  65. data/test/inline_test.rb +11 -11
  66. data/test/instance_test.rb +29 -29
  67. data/test/is_representable_test.rb +10 -10
  68. data/test/json_test.rb +7 -7
  69. data/test/lonely_test.rb +16 -16
  70. data/test/nested_test.rb +7 -7
  71. data/test/object_test.rb +7 -7
  72. data/test/option_test.rb +36 -0
  73. data/test/parse_pipeline_test.rb +3 -3
  74. data/test/pipeline_test.rb +43 -43
  75. data/test/populator_test.rb +15 -15
  76. data/test/prepare_test.rb +2 -2
  77. data/test/private_options_test.rb +2 -2
  78. data/test/reader_writer_test.rb +2 -2
  79. data/test/render_nil_test.rb +2 -2
  80. data/test/represent_test.rb +4 -4
  81. data/test/representable_test.rb +27 -27
  82. data/test/schema_test.rb +5 -5
  83. data/test/serialize_deserialize_test.rb +2 -2
  84. data/test/skip_test.rb +10 -10
  85. data/test/stringify_hash_test.rb +3 -3
  86. data/test/test_helper.rb +4 -2
  87. data/test/uncategorized_test.rb +10 -10
  88. data/test/user_options_test.rb +4 -4
  89. data/test/wrap_test.rb +11 -11
  90. data/test/xml_namespace_test.rb +1 -1
  91. data/test/xml_test.rb +6 -6
  92. data/test/yaml_test.rb +20 -20
  93. metadata +16 -11
  94. data/.travis.yml +0 -16
  95. data/lib/representable/autoload.rb +0 -14
  96. data/test/mongoid_test.rb +0 -31
@@ -1,8 +1,11 @@
1
+ require 'representable/binding'
2
+
1
3
  module Representable
2
4
  module Object
3
5
  class Binding < Representable::Binding
4
6
  def self.build_for(definition) # TODO: remove default arg.
5
7
  return Collection.new(definition) if definition.array?
8
+
6
9
  new(definition)
7
10
  end
8
11
 
@@ -10,6 +13,7 @@ module Representable
10
13
  fragment = hash.send(as) # :getter? no, that's for parsing!
11
14
 
12
15
  return FragmentNotFound if fragment.nil? and typed?
16
+
13
17
  fragment
14
18
  end
15
19
 
@@ -31,4 +35,4 @@ module Representable
31
35
  end
32
36
  end
33
37
  end
34
- end
38
+ end
@@ -26,4 +26,4 @@ module Representable
26
26
  create_representation_with(nil, options, binding_builder)
27
27
  end
28
28
  end
29
- end
29
+ end
@@ -0,0 +1,19 @@
1
+ require "trailblazer/option"
2
+
3
+ module Representable
4
+ # Extend `Trailblazer::Option` to support static values as callables too.
5
+ class Option < ::Trailblazer::Option
6
+ def self.callable?(value)
7
+ [Proc, Symbol, Uber::Callable].any?{ |kind| value.is_a?(kind) }
8
+ end
9
+
10
+ def self.build(value)
11
+ return ->(*) { value } unless callable?(value) # Wrap static `value` into a proc.
12
+ super
13
+ end
14
+ end
15
+
16
+ def self.Option(value)
17
+ ::Representable::Option.build(value)
18
+ end
19
+ end
@@ -4,11 +4,12 @@ module Representable
4
4
  class Pipeline < Array
5
5
  Stop = Class.new
6
6
 
7
- # options is mutuable.
7
+ # options is mutable.
8
8
  def call(input, options)
9
9
  inject(input) do |memo, block|
10
10
  res = evaluate(block, memo, options)
11
- return(Stop)if Stop == res
11
+ return(Stop) if Stop == res
12
+
12
13
  res
13
14
  end
14
15
  end
@@ -2,7 +2,8 @@
2
2
  module Representable
3
3
  module Binding::Factories
4
4
  def pipeline_for(name, input, options)
5
- return yield unless proc = @definition[name]
5
+ return yield unless (proc = @definition[name])
6
+
6
7
  # proc.(self, options)
7
8
  instance_exec(input, options, &proc)
8
9
  end
@@ -11,6 +12,7 @@ module Representable
11
12
  def collect_for(item_functions)
12
13
  return [Collect[*item_functions]] if array?
13
14
  return [Collect::Hash[*item_functions]] if self[:hash]
15
+
14
16
  item_functions
15
17
  end
16
18
 
@@ -92,4 +94,4 @@ module Representable
92
94
  funcs << (self[:setter] ? Setter : SetValue)
93
95
  end
94
96
  end
95
- end
97
+ end
@@ -21,7 +21,7 @@ module Representable
21
21
  def self.apply!(options)
22
22
  return unless populator = options[:populator]
23
23
 
24
- options[:parse_pipeline] = ->(input, opts) do
24
+ options[:parse_pipeline] = ->(_input, _opts) do
25
25
  pipeline = Pipeline[*parse_functions] # TODO: AssignFragment
26
26
  pipeline = Pipeline::Insert.(pipeline, SetValue, delete: true) # remove the setter function.
27
27
  pipeline = Pipeline::Insert.(pipeline, populator, replace: CreateObject::Populator) # let the actual populator do the job.
@@ -1,6 +1,7 @@
1
1
  module Representable::Represent
2
2
  def represent(represented, array_class=Array)
3
3
  return for_collection.prepare(represented) if represented.is_a?(array_class)
4
+
4
5
  prepare(represented)
5
6
  end
6
7
  end
@@ -3,7 +3,7 @@ module Representable
3
3
  options[:binding].evaluate_option(:getter, input, options)
4
4
  end
5
5
 
6
- GetValue = ->(input, options) { options[:binding].send(:exec_context, options).public_send(options[:binding].getter) }
6
+ GetValue = ->(_input, options) { options[:binding].send(:exec_context, options).public_send(options[:binding].getter) }
7
7
 
8
8
  Writer = ->(input, options) do
9
9
  options[:binding].evaluate_option(:writer, input, options)
@@ -37,6 +37,7 @@ module Representable
37
37
 
38
38
  Serialize = ->(input, options) do
39
39
  return if input.nil? # DISCUSS: how can we prevent that?
40
+
40
41
  binding, options = options[:binding], options[:options] # FIXME: rename to :local_options.
41
42
 
42
43
  options_for_nested = OptionsForNested.(options, binding)
@@ -1,3 +1,3 @@
1
1
  module Representable
2
- VERSION = "3.0.4"
2
+ VERSION = "3.2.0"
3
3
  end
@@ -1,10 +1,8 @@
1
1
  require 'representable/binding'
2
- require 'representable/hash/binding.rb'
3
2
 
4
3
  module Representable
5
4
  module XML
6
- module_function
7
- def Node(document, name, attributes={})
5
+ module_function def Node(document, name, attributes={})
8
6
  node = Nokogiri::XML::Node.new(name.to_s, document) # Java::OrgW3cDom::DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
9
7
 
10
8
  attributes.each { |k, v| node[k] = v } # TODO: benchmark.
@@ -18,6 +16,7 @@ module Representable
18
16
  return AttributeHash.new(definition) if definition.hash? and definition[:use_attributes]
19
17
  return Attribute.new(definition) if definition[:attribute]
20
18
  return Content.new(definition) if definition[:content]
19
+
21
20
  new(definition)
22
21
  end
23
22
 
@@ -25,7 +24,7 @@ module Representable
25
24
  wrap_node = parent
26
25
 
27
26
  if wrap = self[:wrap]
28
- parent << wrap_node = XML::Node(parent, wrap)
27
+ parent << wrap_node = XML::Node(parent.document, wrap)
29
28
  end
30
29
 
31
30
  wrap_node << serialize_for(fragments, parent, as)
@@ -40,7 +39,7 @@ module Representable
40
39
 
41
40
  # Creates wrapped node for the property.
42
41
  def serialize_for(value, parent, as)
43
- node = XML::Node(parent, as) # node doesn't have attr="" attributes!!!
42
+ node = XML::Node(parent.document, as) # node doesn't have attr="" attributes!!!
44
43
  serialize_node(node, value, as)
45
44
  end
46
45
 
@@ -107,7 +106,7 @@ module Representable
107
106
  class Hash < Collection
108
107
  def serialize_for(value, parent, as)
109
108
  set_for(parent, value.collect do |k, v|
110
- node = XML::Node(parent, k)
109
+ node = XML::Node(parent.document, k)
111
110
  serialize_node(node, v, as)
112
111
  end)
113
112
  end
@@ -1,13 +1,14 @@
1
- require 'representable'
1
+ gem 'nokogiri', '> 1.10.8'
2
+ require 'nokogiri'
2
3
 
3
- begin
4
- require 'nokogiri'
5
- rescue LoadError => _
6
- abort "Missing dependency 'nokogiri' for Representable::XML. See dependencies section in README.md for details."
7
- end
4
+ require 'representable'
8
5
 
9
6
  module Representable
10
7
  module XML
8
+ autoload :Binding, 'representable/xml/binding'
9
+ autoload :Collection, 'representable/xml/collection'
10
+ autoload :Namespace, 'representable/xml/namespace'
11
+
11
12
  def self.included(base)
12
13
  base.class_eval do
13
14
  include Representable
@@ -71,7 +72,3 @@ module Representable
71
72
  end
72
73
  end
73
74
  end
74
-
75
- require "representable/xml/binding"
76
- require "representable/xml/collection"
77
- require "representable/xml/namespace"
@@ -5,6 +5,7 @@ module Representable
5
5
  class Binding < Representable::Hash::Binding
6
6
  def self.build_for(definition)
7
7
  return Collection.new(definition) if definition.array?
8
+
8
9
  new(definition)
9
10
  end
10
11
 
@@ -1,9 +1,9 @@
1
1
  require 'psych'
2
- require 'representable/hash'
3
- require 'representable/yaml/binding'
2
+ require 'representable'
4
3
 
5
4
  module Representable
6
5
  module YAML
6
+ autoload :Binding, 'representable/yaml/binding'
7
7
  include Hash
8
8
 
9
9
  def self.included(base)
@@ -40,7 +40,7 @@ module Representable
40
40
  stream.to_yaml
41
41
  end
42
42
 
43
- alias_method :render, :to_yaml
43
+ alias_method :render, :to_yaml
44
44
  alias_method :parse, :from_yaml
45
45
  end
46
46
  end
data/lib/representable.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  require "uber/delegates"
2
2
  require "uber/callable"
3
- require "declarative/option"
4
3
  require "declarative/schema"
5
4
 
5
+ require "representable/option"
6
6
  require "representable/config"
7
7
  require "representable/definition"
8
8
  require "representable/declarative"
@@ -16,6 +16,17 @@ require "representable/for_collection"
16
16
  require "representable/represent"
17
17
 
18
18
  module Representable
19
+ autoload :Binding, 'representable/binding'
20
+ autoload :HashMethods, 'representable/hash_methods'
21
+ autoload :Decorator, 'representable/decorator'
22
+
23
+ autoload :Hash, 'representable/hash'
24
+ autoload :JSON, 'representable/json'
25
+ autoload :Object, 'representable/object'
26
+ autoload :YAML, 'representable/yaml'
27
+ autoload :XML, 'representable/xml'
28
+
29
+
19
30
  attr_writer :representable_attrs
20
31
 
21
32
  def self.included(base)
@@ -32,7 +43,7 @@ module Representable
32
43
  private
33
44
  # Reads values from +doc+ and sets properties accordingly.
34
45
  def update_properties_from(doc, options, format)
35
- propagated_options = normalize_options(options)
46
+ propagated_options = normalize_options(**options)
36
47
 
37
48
  representable_map!(doc, propagated_options, format, :uncompile_fragment)
38
49
  represented
@@ -40,25 +51,12 @@ private
40
51
 
41
52
  # Compiles the document going through all properties.
42
53
  def create_representation_with(doc, options, format)
43
- propagated_options = normalize_options(options)
54
+ propagated_options = normalize_options(**options)
44
55
 
45
56
  representable_map!(doc, propagated_options, format, :compile_fragment)
46
57
  doc
47
58
  end
48
59
 
49
- class Binding::Map < Array
50
- def call(method, options)
51
- each do |bin|
52
- options[:binding] = bin # this is so much faster than options.merge().
53
- bin.send(method, options)
54
- end
55
- end
56
-
57
- # TODO: Merge with Definitions.
58
- def <<(binding) # can be slow. this is compile time code.
59
- (existing = find { |bin| bin.name == binding.name }) ? self[index(existing)] = binding : super(binding)
60
- end
61
- end
62
60
 
63
61
  def representable_map(options, format)
64
62
  Binding::Map.new(representable_bindings_for(format, options))
@@ -74,9 +72,8 @@ private
74
72
  representable_attrs.collect {|definition| format.build(definition) }
75
73
  end
76
74
 
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.
75
+ def normalize_options(user_options: {}, **options)
76
+ { user_options: user_options }.merge(options)
80
77
  end
81
78
 
82
79
  # Prepares options for a particular nested representer.
@@ -96,8 +93,8 @@ private
96
93
  @representable_attrs ||= self.class.definitions
97
94
  end
98
95
 
99
- def representation_wrap(*args)
100
- representable_attrs.wrap_for(represented, *args)
96
+ def representation_wrap(options = {})
97
+ representable_attrs.wrap_for(represented, options)
101
98
  end
102
99
 
103
100
  def represented
@@ -118,8 +115,4 @@ private
118
115
  represented.extend(self)
119
116
  end
120
117
  end
121
-
122
- # require "representable/deprecations"
123
118
  end
124
-
125
- require 'representable/autoload'
@@ -19,16 +19,16 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
  spec.license = "MIT"
21
21
 
22
- spec.required_ruby_version = '>= 1.9.3'
22
+ spec.required_ruby_version = '>= 2.4.0'
23
23
 
24
24
  spec.add_dependency "uber", "< 0.2.0"
25
25
  spec.add_dependency "declarative", "< 0.1.0"
26
- spec.add_dependency "declarative-option", "< 0.2.0"
26
+ spec.add_dependency "trailblazer-option", ">= 0.1.1", "< 0.2.0"
27
27
 
28
28
  spec.add_development_dependency "rake"
29
29
  spec.add_development_dependency "test_xml", ">= 0.1.6"
30
30
  spec.add_development_dependency "minitest"
31
31
  spec.add_development_dependency "virtus"
32
- spec.add_development_dependency "multi_json"
32
+ spec.add_development_dependency "dry-types"
33
33
  spec.add_development_dependency "ruby-prof" if RUBY_ENGINE == "ruby" # mri
34
34
  end
data/test/as_test.rb CHANGED
@@ -17,7 +17,7 @@ class AsTest < MiniTest::Spec
17
17
  end
18
18
 
19
19
  it { render(song).must_equal_document output }
20
- it { parse(song, input).name.must_equal "Wie Es Geht" }
20
+ it { _(parse(song, input).name).must_equal "Wie Es Geht" }
21
21
  end
22
22
 
23
23
 
@@ -27,7 +27,7 @@ class AsTest < MiniTest::Spec
27
27
  end
28
28
 
29
29
  it { render(song).must_equal_document({"Song" => "Revolution"}) }
30
- it { parse(song, {"Song" => "Wie Es Geht"}).name.must_equal "Wie Es Geht" }
30
+ it { _(parse(song, {"Song" => "Wie Es Geht"}).name).must_equal "Wie Es Geht" }
31
31
  end
32
32
 
33
33
 
@@ -37,7 +37,7 @@ class AsTest < MiniTest::Spec
37
37
  end
38
38
 
39
39
  it { render(song, user_options:{volume: 1}).must_equal_document({"{:volume=>1}" => "Revolution"}) }
40
- it { parse(song, {"{:volume=>1}" => "Wie Es Geht"}, user_options: {volume: 1}).name.must_equal "Wie Es Geht" }
40
+ it { _(parse(song, {"{:volume=>1}" => "Wie Es Geht"}, user_options: {volume: 1}).name).must_equal "Wie Es Geht" }
41
41
  end
42
42
  end
43
43
  end
@@ -60,6 +60,6 @@ class AsXmlTest < MiniTest::Spec
60
60
 
61
61
  it do
62
62
  skip
63
- representer.new(Album.new(Band.new("Offspring"))).to_xml.must_equal ""
63
+ _(representer.new(Album.new(Band.new("Offspring"))).to_xml).must_equal ""
64
64
  end
65
65
  end
data/test/binding_test.rb CHANGED
@@ -8,16 +8,16 @@ class BindingTest < MiniTest::Spec
8
8
  let(:binding) { Binding.new(render_nil_definition) }
9
9
 
10
10
  # don't skip when present.
11
- it { binding.skipable_empty_value?("Disconnect, Disconnect").must_equal false }
11
+ it { _(binding.skipable_empty_value?("Disconnect, Disconnect")).must_equal false }
12
12
 
13
13
  # don't skip when it's nil and render_nil: true
14
- it { binding.skipable_empty_value?(nil).must_equal false }
14
+ it { _(binding.skipable_empty_value?(nil)).must_equal false }
15
15
 
16
16
  # skip when nil and :render_nil undefined.
17
- it { Binding.new(Representable::Definition.new(:song)).skipable_empty_value?(nil).must_equal true }
17
+ it { _(Binding.new(Representable::Definition.new(:song)).skipable_empty_value?(nil)).must_equal true }
18
18
 
19
19
  # don't skip when nil and :render_nil undefined.
20
- it { Binding.new(Representable::Definition.new(:song)).skipable_empty_value?("Fatal Flu").must_equal false }
20
+ it { _(Binding.new(Representable::Definition.new(:song)).skipable_empty_value?("Fatal Flu")).must_equal false }
21
21
  end
22
22
 
23
23
 
@@ -26,21 +26,21 @@ class BindingTest < MiniTest::Spec
26
26
  let(:binding) { Binding.new(definition) }
27
27
 
28
28
  # return value when value present.
29
- it { binding.default_for("Black And Blue").must_equal "Black And Blue" }
29
+ it { _(binding.default_for("Black And Blue")).must_equal "Black And Blue" }
30
30
 
31
31
  # return false when value false.
32
- it { binding.default_for(false).must_equal false }
32
+ it { _(binding.default_for(false)).must_equal false }
33
33
 
34
34
  # return default when value nil.
35
- it { binding.default_for(nil).must_equal "Insider" }
35
+ it { _(binding.default_for(nil)).must_equal "Insider" }
36
36
 
37
37
  # return nil when value nil and render_nil: true.
38
- it { Binding.new(render_nil_definition).default_for(nil).must_be_nil }
38
+ it { _(Binding.new(render_nil_definition).default_for(nil)).must_be_nil }
39
39
 
40
40
  # return nil when value nil and render_nil: true, even when :default is set" do
41
- it { Binding.new(Representable::Definition.new(:song, :render_nil => true, :default => "The Quest")).default_for(nil).must_be_nil }
41
+ it { _(Binding.new(Representable::Definition.new(:song, :render_nil => true, :default => "The Quest")).default_for(nil)).must_be_nil }
42
42
 
43
43
  # return nil if no :default
44
- it { Binding.new(Representable::Definition.new(:song)).default_for(nil).must_be_nil }
44
+ it { _(Binding.new(Representable::Definition.new(:song)).default_for(nil)).must_be_nil }
45
45
  end
46
46
  end
data/test/cached_test.rb CHANGED
@@ -64,7 +64,7 @@ class CachedTest < MiniTest::Spec
64
64
  # album2 = Model::Album.new("Louder And Even More Dangerous", [song2, song])
65
65
 
66
66
  # makes sure options are passed correctly.
67
- representer.to_hash(user_options: {volume: 9}).must_equal({"name"=>"Live And Dangerous",
67
+ _(representer.to_hash(user_options: {volume: 9})).must_equal({"name"=>"Live And Dangerous",
68
68
  "songs"=>[{"title"=>"Jailbreak:{:volume=>9}"}, {"title"=>"Southbound:{:volume=>9}"}, {"title"=>"Emerald:{:volume=>9}"}]}) # called in Deserializer/Serializer
69
69
 
70
70
  # representer becomes reusable as it is stateless.
@@ -81,22 +81,22 @@ class CachedTest < MiniTest::Spec
81
81
  data = Profiler.profile { representer.to_hash }
82
82
 
83
83
  # 3 songs get decorated.
84
- data.must_match(/3\s*Representable::Function::Decorate#call/m)
84
+ _(data).must_match(/3\s*Representable::Function::Decorate#call/m)
85
85
  # These weird Regexp bellow are a quick workaround to accomodate
86
86
  # the different profiler result formats.
87
87
  # - "3 <Class::Representable::Decorator>#prepare" -> At MRI Ruby
88
88
  # - "3 Representable::Decorator.prepare" -> At JRuby
89
89
 
90
90
  # 3 nested decorator is instantiated for 3 Songs, though.
91
- data.must_match(/3\s*(<Class::)?Representable::Decorator\>?[\#.]prepare/m)
91
+ _(data).must_match(/3\s*(<Class::)?Representable::Decorator\>?[\#.]prepare/m)
92
92
  # no Binding is instantiated at runtime.
93
- data.wont_match "Representable::Binding#initialize"
93
+ _(data).wont_match "Representable::Binding#initialize"
94
94
  # 2 mappers for Album, Song
95
95
  # data.must_match "2 Representable::Mapper::Methods#initialize"
96
96
  # title, songs, 3x title, composer
97
- data.must_match(/8\s*Representable::Binding[#\.]render_pipeline/m)
98
- data.wont_match "render_functions"
99
- data.wont_match "Representable::Binding::Factories#render_functions"
97
+ _(data).must_match(/8\s*Representable::Binding[#\.]render_pipeline/m)
98
+ _(data).wont_match "render_functions"
99
+ _(data).wont_match "Representable::Binding::Factories#render_functions"
100
100
  end
101
101
  end
102
102
 
@@ -118,14 +118,14 @@ class CachedTest < MiniTest::Spec
118
118
 
119
119
  AlbumRepresenter.new(album).from_hash(album_hash)
120
120
 
121
- album.songs.size.must_equal 3
122
- album.name.must_equal "Louder And Even More Dangerous"
123
- album.songs[0].title.must_equal "Southbound"
124
- album.songs[0].composer.name.must_equal "Lynott"
125
- album.songs[1].title.must_equal "Jailbreak"
126
- album.songs[1].composer.name.must_equal "Phil Lynott"
127
- album.songs[2].title.must_equal "Emerald"
128
- album.songs[2].composer.must_be_nil
121
+ _(album.songs.size).must_equal 3
122
+ _(album.name).must_equal "Louder And Even More Dangerous"
123
+ _(album.songs[0].title).must_equal "Southbound"
124
+ _(album.songs[0].composer.name).must_equal "Lynott"
125
+ _(album.songs[1].title).must_equal "Jailbreak"
126
+ _(album.songs[1].composer.name).must_equal "Phil Lynott"
127
+ _(album.songs[2].title).must_equal "Emerald"
128
+ _(album.songs[2].composer).must_be_nil
129
129
 
130
130
  # TODO: test options.
131
131
  end
@@ -139,12 +139,12 @@ class CachedTest < MiniTest::Spec
139
139
  # only 2 nested decorators are instantiated, Song, and Artist.
140
140
  # Didn't like the regexp?
141
141
  # MRI and JRuby has different output formats. See note above.
142
- data.must_match(/5\s*(<Class::)?Representable::Decorator>?[#\.]prepare/)
142
+ _(data).must_match(/5\s*(<Class::)?Representable::Decorator>?[#\.]prepare/)
143
143
  # a total of 5 properties in the object graph.
144
- data.wont_match "Representable::Binding#initialize"
144
+ _(data).wont_match "Representable::Binding#initialize"
145
145
 
146
- data.wont_match "parse_functions" # no pipeline creation.
147
- data.must_match(/10\s*Representable::Binding[#\.]parse_pipeline/)
146
+ _(data).wont_match "parse_functions" # no pipeline creation.
147
+ _(data).must_match(/10\s*Representable::Binding[#\.]parse_pipeline/)
148
148
  # three mappers for Album, Song, composer
149
149
  # data.must_match "3 Representable::Mapper::Methods#initialize"
150
150
  # # 6 deserializers as the songs collection uses 2.
data/test/class_test.rb CHANGED
@@ -20,8 +20,8 @@ class ClassTest < BaseTest
20
20
 
21
21
  it "creates fresh instance and doesn't extend" do
22
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"
23
+ _(song).must_be_instance_of RepresentingSong
24
+ _(song.name).must_equal "Captured"
25
25
  end
26
26
  end
27
27
 
@@ -33,8 +33,8 @@ class ClassTest < BaseTest
33
33
 
34
34
  it "creates fresh instance and doesn't extend" do
35
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"
36
+ _(song).must_be_instance_of RepresentingSong
37
+ _(song.name).must_equal "Captured"
38
38
  end
39
39
  end
40
40
 
@@ -69,7 +69,7 @@ class ClassTest < BaseTest
69
69
  property :song, :class => lambda { |options| _klass.args=([options[:fragment],options[:user_options]]); _klass }
70
70
  end
71
71
 
72
- it { representer.prepare(OpenStruct.new).from_hash({"song" => {"name" => "Captured"}}, user_options: {volume: true}).song.class.args.
72
+ it { _(representer.prepare(OpenStruct.new).from_hash({"song" => {"name" => "Captured"}}, user_options: {volume: true}).song.class.args).
73
73
  must_equal([{"name"=>"Captured"}, {:volume=>true}]) }
74
74
  end
75
75
 
@@ -90,7 +90,7 @@ class ClassTest < BaseTest
90
90
  collection :songs, :class => lambda { |options| _klass.args=([options[:fragment],options[:index],options[:user_options]]); _klass }
91
91
  end
92
92
 
93
- it { representer.prepare(OpenStruct.new).from_hash({"songs" => [{"name" => "Captured"}]}, user_options: {volume: true}).songs.first.class.args.
93
+ it { _(representer.prepare(OpenStruct.new).from_hash({"songs" => [{"name" => "Captured"}]}, user_options: {volume: true}).songs.first.class.args).
94
94
  must_equal([{"name"=>"Captured"}, 0, {:volume=>true}]) }
95
95
  end
96
96
 
@@ -109,7 +109,7 @@ class ClassTest < BaseTest
109
109
  end
110
110
 
111
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]
112
+ _(representer.prepare(OpenStruct.new).from_hash({"song" => 1}).song).must_equal [1,2,3,4]
113
113
  end
114
114
  end
115
115
  end
@@ -1,52 +1,63 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
  require 'representable/coercion'
3
5
 
4
- class VirtusCoercionTest < MiniTest::Spec
6
+ class CoercionTest < MiniTest::Spec
5
7
  representer! do
6
8
  include Representable::Coercion
7
9
 
8
10
  property :title # no coercion.
9
- property :length, :type => Float
11
+ property :length, type: Representable::Coercion::Types::Params::Float
10
12
 
11
- property :band, :class => OpenStruct do
12
- property :founded, :type => Integer
13
+ property :band, class: OpenStruct do
14
+ property :founded, type: Representable::Coercion::Types::Params::Integer
13
15
  end
14
16
 
15
- collection :songs, :class => OpenStruct do
16
- property :ok, :type => Virtus::Attribute::Boolean
17
+ collection :songs, class: OpenStruct do
18
+ property :ok, type: Representable::Coercion::Types::Params::Bool
17
19
  end
18
20
  end
19
21
 
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)]) }
22
+ let(:album) do
23
+ OpenStruct.new(title: 'Dire Straits', length: 41.34,
24
+ band: OpenStruct.new(founded: '1977'),
25
+ songs: [OpenStruct.new(ok: 1), OpenStruct.new(ok: 0)])
26
+ end
23
27
 
24
- it { album.extend(representer).to_hash.must_equal({"title"=>"Dire Straits", "length"=>41.34, "band"=>{"founded"=>1977}, "songs"=>[{"ok"=>true}, {"ok"=>false}]}) }
28
+ it do
29
+ _(album.extend(representer).to_hash).must_equal({ 'title' => 'Dire Straits',
30
+ 'length' => 41.34,
31
+ 'band' => { 'founded' => 1977 },
32
+ 'songs' => [{ 'ok' => true }, { 'ok' => false }] })
33
+ end
25
34
 
26
35
  it {
27
36
  album = OpenStruct.new
28
37
  album.extend(representer)
29
- album.from_hash({"title"=>"Dire Straits", "length"=>"41.34", "band"=>{"founded"=>"1977"}, "songs"=>[{"ok"=>1}, {"ok"=>0}]})
38
+ album.from_hash({ 'title' => 'Dire Straits',
39
+ 'length' => '41.34',
40
+ 'band' => { 'founded' => '1977' },
41
+ 'songs' => [{ 'ok' => 1 }, { 'ok' => 0 }] })
30
42
 
31
43
  # it
32
- album.length.must_equal 41.34
33
- album.band.founded.must_equal 1977
34
- album.songs[0].ok.must_equal true
44
+ _(album.length).must_equal 41.34
45
+ _(album.band.founded).must_equal 1977
46
+ _(album.songs[0].ok).must_equal true
35
47
  }
36
48
 
37
-
38
- describe "with user :parse_filter and :render_filter" do
49
+ describe 'with user :parse_filter and :render_filter' do
39
50
  representer! do
40
51
  include Representable::Coercion
41
52
 
42
- property :length, :type => Float,
43
- :parse_filter => lambda { |input, options| "#{input}.1" }, # happens BEFORE coercer.
44
- :render_filter => lambda { |fragment,*| "#{fragment}.1" }
53
+ property :length, type: Representable::Coercion::Types::Params::Float,
54
+ parse_filter: ->(input, _options) { "#{input}.1" }, # happens BEFORE coercer.
55
+ render_filter: ->(fragment, *) { "#{fragment}.1" }
45
56
  end
46
57
 
47
58
  # user's :parse_filter(s) are run before coercion.
48
- it { OpenStruct.new.extend(representer).from_hash("length"=>"1").length.must_equal 1.1 }
59
+ it { _(OpenStruct.new.extend(representer).from_hash('length' => '1').length).must_equal 1.1 }
49
60
  # user's :render_filter(s) are run before coercion.
50
- it { OpenStruct.new(:length=>1).extend(representer).to_hash.must_equal({"length" => 1.1}) }
61
+ it { _(OpenStruct.new(length: 1).extend(representer).to_hash).must_equal({ 'length' => 1.1 }) }
51
62
  end
52
- end
63
+ end