representable 3.1.1 → 3.3.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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +17 -4
  3. data/.github/workflows/ci_jruby.yml +21 -0
  4. data/.github/workflows/ci_truffleruby.yml +19 -0
  5. data/CHANGES.md +9 -0
  6. data/Gemfile +1 -1
  7. data/README.md +8 -10
  8. data/lib/representable/hash/binding.rb +1 -0
  9. data/lib/representable/json.rb +14 -2
  10. data/lib/representable/version.rb +1 -1
  11. data/lib/representable/xml/binding.rb +3 -10
  12. data/lib/representable/xml.rb +7 -0
  13. data/representable.gemspec +1 -3
  14. data/test/as_test.rb +8 -13
  15. data/test/benchmarking.rb +20 -25
  16. data/test/binding_test.rb +13 -5
  17. data/test/cached_test.rb +55 -35
  18. data/test/class_test.rb +46 -33
  19. data/test/coercion_test.rb +29 -19
  20. data/test/config/inherit_test.rb +12 -17
  21. data/test/config_test.rb +5 -7
  22. data/test/decorator_scope_test.rb +13 -11
  23. data/test/decorator_test.rb +11 -11
  24. data/test/default_test.rb +2 -2
  25. data/test/defaults_options_test.rb +37 -9
  26. data/test/definition_test.rb +10 -12
  27. data/test/examples/example.rb +43 -38
  28. data/test/examples/object.rb +7 -6
  29. data/test/exec_context_test.rb +18 -23
  30. data/test/features_test.rb +29 -10
  31. data/test/filter_test.rb +29 -20
  32. data/test/for_collection_test.rb +12 -15
  33. data/test/generic_test.rb +15 -22
  34. data/test/getter_setter_test.rb +11 -6
  35. data/test/hash_bindings_test.rb +21 -12
  36. data/test/hash_test.rb +53 -38
  37. data/test/heritage_test.rb +0 -1
  38. data/test/if_test.rb +25 -21
  39. data/test/include_exclude_test.rb +24 -16
  40. data/test/inherit_test.rb +114 -27
  41. data/test/inline_test.rb +42 -33
  42. data/test/instance_test.rb +151 -109
  43. data/test/is_representable_test.rb +19 -17
  44. data/test/json_test.rb +48 -46
  45. data/test/lonely_test.rb +35 -33
  46. data/test/nested_test.rb +16 -19
  47. data/test/object_test.rb +6 -6
  48. data/test/option_test.rb +10 -8
  49. data/test/parse_pipeline_test.rb +21 -15
  50. data/test/pipeline_test.rb +144 -108
  51. data/test/populator_test.rb +18 -15
  52. data/test/prepare_test.rb +15 -17
  53. data/test/private_options_test.rb +3 -2
  54. data/test/reader_writer_test.rb +4 -4
  55. data/test/realistic_benchmark.rb +21 -27
  56. data/test/render_nil_test.rb +1 -1
  57. data/test/represent_test.rb +14 -18
  58. data/test/representable_test.rb +86 -53
  59. data/test/schema_test.rb +51 -21
  60. data/test/serialize_deserialize_test.rb +14 -14
  61. data/test/skip_test.rb +39 -28
  62. data/test/stringify_hash_test.rb +29 -31
  63. data/test/test_helper.rb +31 -25
  64. data/test/test_helper_test.rb +7 -7
  65. data/test/uncategorized_test.rb +20 -15
  66. data/test/user_options_test.rb +12 -3
  67. data/test/wrap_test.rb +27 -17
  68. data/test/xml_assertions.rb +29 -0
  69. data/test/xml_bindings_test.rb +5 -8
  70. data/test/xml_namespace_test.rb +46 -39
  71. data/test/xml_test.rb +109 -88
  72. data/test/yaml_test.rb +73 -51
  73. metadata +11 -97
  74. data/lib/representable/virtus_coercion.rb +0 -38
  75. data/test/virtus_coercion_test.rb +0 -52
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7fac946d38143671ea43e0a6981d35dc7e8e8a0026af631fe53bb67d30f413c0
4
- data.tar.gz: 3f98fb8a4ff2ea929ecd3afd9c97bc32fa7b7959d696a5c4ea4d5c9aecfac4d4
3
+ metadata.gz: 2bb7b8770886210c259064f3d2ba30d7fd3b4e50350e0a9cbd98640261ac3879
4
+ data.tar.gz: 664ee784de146034f31308b2207a121e0a1fbeea38ca3989fc09a1fe04016bc1
5
5
  SHA512:
6
- metadata.gz: 781a63fe0c5a650bc54d007dd6c16b20dec422b8312fa831b938ad0b78a1ffe5c6cbf640de1406574943035cbbc03925446e9ddd0cc640c1a0c9e9212b75d71e
7
- data.tar.gz: fbedd21d3373cca798829c164357cc8c6d1470c9fe16b4d404b67a1df0f9eeebdb13a1ae262f585d54c4a2c4209573b23f211b4ca1430e801c21dca4c9451b4f
6
+ metadata.gz: 1ecad360b289f31fa0ed925369e3541cb580154c158c1f6b21dd0c0e9ebd98945fe1534292e882521ef3d6c0a24447f55a1b1267deb29282af0d7d1d0b8970c9
7
+ data.tar.gz: dce51b8db19df9005a598272847b55088a9f0ee91c6e4f5aed33075ac43bc28b8edac1a76a020be2e195c3358dc13b1a698ae78cb0d323ce2c3c4ede4a52c912
@@ -1,3 +1,6 @@
1
+ ## This file is managed by Terraform.
2
+ ## Do not modify this file directly, as it may be overwritten.
3
+ ## Please open an issue instead.
1
4
  name: CI
2
5
  on: [push, pull_request]
3
6
  jobs:
@@ -5,13 +8,23 @@ jobs:
5
8
  strategy:
6
9
  fail-fast: false
7
10
  matrix:
8
- # Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0'
9
- ruby: [2.5, 2.6, 2.7, '3.0', head]
11
+ ruby: ["3.0", "3.1", "3.2", '3.3', '3.4', '4.0']
10
12
  runs-on: ubuntu-latest
11
13
  steps:
12
- - uses: actions/checkout@v2
14
+ - uses: actions/checkout@v7
13
15
  - uses: ruby/setup-ruby@v1
14
16
  with:
15
17
  ruby-version: ${{ matrix.ruby }}
16
- bundler-cache: true # runs 'bundle install' and caches installed gems automatically
18
+ bundler-cache: true
19
+ - run: bundle exec rake
20
+
21
+ test-head:
22
+ continue-on-error: true
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - uses: actions/checkout@v7
26
+ - uses: ruby/setup-ruby@v1
27
+ with:
28
+ ruby-version: head
29
+ bundler-cache: true
17
30
  - run: bundle exec rake
@@ -0,0 +1,21 @@
1
+ ## This file is managed by Terraform.
2
+ ## Do not modify this file directly, as it may be overwritten.
3
+ ## Please open an issue instead.
4
+ name: CI JRuby
5
+ on: [push, pull_request]
6
+ jobs:
7
+ test:
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ ruby: [jruby, jruby-head]
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v7
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: ${{ matrix.ruby }}
18
+ bundler-cache: true
19
+ - run: bundle exec rake
20
+ env:
21
+ JRUBY_OPTS: --profile.api
@@ -0,0 +1,19 @@
1
+ ## This file is managed by Terraform.
2
+ ## Do not modify this file directly, as it may be overwritten.
3
+ ## Please open an issue instead.
4
+ name: CI TruffleRuby
5
+ on: [push, pull_request]
6
+ jobs:
7
+ test:
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ ruby: [truffleruby, truffleruby-head]
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v7
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: ${{ matrix.ruby }}
18
+ bundler-cache: true
19
+ - run: bundle exec rake
data/CHANGES.md CHANGED
@@ -1,3 +1,12 @@
1
+ # 3.3.0
2
+
3
+ * Drop support for Ruby < 3.0.0.
4
+ * Fix deprecations with `MultiJson`.
5
+
6
+ # 3.2.0
7
+ * Drop support for Virtus Coercion
8
+ * Fix deprecation warning with Nokogiri 1.13.0
9
+
1
10
  # 3.1.1
2
11
 
3
12
  * Upgrade `trailblazer-option` to `0.1.1` which supports passing an empty `keyword_arguments`.
data/Gemfile CHANGED
@@ -6,6 +6,6 @@ group :test do
6
6
  gem "minitest-line"
7
7
  gem "multi_json", require: false
8
8
  gem "nokogiri", require: false
9
+ gem "ostruct"
9
10
  end
10
- gem 'pry-byebug'
11
11
 
data/README.md CHANGED
@@ -1,21 +1,19 @@
1
1
  # Representable
2
2
 
3
3
  Representable maps Ruby objects to documents and back.
4
-
5
- [![Gitter Chat](https://badges.gitter.im/trailblazer/chat.svg)](https://gitter.im/trailblazer/chat)
6
- [![TRB Newsletter](https://img.shields.io/badge/TRB-newsletter-lightgrey.svg)](http://trailblazer.to/newsletter/)
7
- [![Build
8
- Status](https://travis-ci.org/trailblazer/representable.svg)](https://travis-ci.org/trailblazer/representable)
4
+ ![Build
5
+ Status](https://github.com/trailblazer/representable/actions/workflows/ci.yml/badge.svg?branch=master)
9
6
  [![Gem Version](https://badge.fury.io/rb/representable.svg)](http://badge.fury.io/rb/representable)
10
7
 
8
+
11
9
  In other words: Take an object and decorate it with a representer module. This will allow you to render a JSON, XML or YAML document from that object. But that's only half of it! You can also use representers to parse a document and create or populate an object.
12
10
 
13
- Representable is helpful for all kind of mappings, rendering and parsing workflows. However, it is mostly useful in API code. Are you planning to write a real REST API with representable? Then check out the [Roar](http://github.com/apotonick/roar) gem first, save work and time and make the world a better place instead.
11
+ Representable is helpful for all kind of mappings, rendering and parsing workflows. However, it is mostly useful in API code. Are you planning to write a real REST API with representable? Then check out the [Roar](https://github.com/trailblazer/roar) gem first, save work and time and make the world a better place instead.
14
12
 
15
13
 
16
14
  ## Full Documentation
17
15
 
18
- Representable comes with a rich set of options and semantics for parsing and rendering documents. Its [full documentation](http://trailblazer.to/gems/representable/3.0/api.html) can be found on the Trailblazer site.
16
+ Representable comes with a rich set of options and semantics for parsing and rendering documents. Its [full documentation](https://trailblazer.to/2.1/docs/representable.html) can be found on the Trailblazer site.
19
17
 
20
18
  ## Example
21
19
 
@@ -64,7 +62,7 @@ song = SongRepresenter.new(song).from_json(%{ {"title":"Roxanne"} })
64
62
  #=> #<Song title="Roxanne", track=nil>
65
63
  ```
66
64
 
67
- Note that parsing hashes per default does [require string keys](http://trailblazer.to/gems/representable/3.0/api.html#symbol-keys) and does _not_ pick up symbol keys.
65
+ Note that parsing hashes per default does [require string keys](https://trailblazer.to/2.1/docs/representable.html#representable-api-symbol-keys) and does _not_ pick up symbol keys.
68
66
 
69
67
 
70
68
  ## Collections
@@ -137,7 +135,7 @@ end
137
135
 
138
136
  Representable has many more features and can literally parse and render any kind of document to an arbitrary Ruby object graph.
139
137
 
140
- Please check the [official documentation for more](http://trailblazer.to/gems/representable/).
138
+ Please check the [official documentation for more](https://trailblazer.to/2.1/docs/representable.html#representable-api).
141
139
 
142
140
 
143
141
  ## Installation
@@ -172,4 +170,4 @@ Representable started as a heavily simplified fork of the ROXML gem. Big thanks
172
170
  * Copyright (c) 2011-2020 Nick Sutterer <apotonick@gmail.com>
173
171
  * ROXML is Copyright (c) 2004-2009 Ben Woosley, Zak Mandhro and Anders Engstrom.
174
172
 
175
- Representable is released under the [MIT License](http://www.opensource.org/licenses/MIT).
173
+ Representable is released under the [MIT License](https://www.opensource.org/licenses/MIT).
@@ -10,6 +10,7 @@ module Representable
10
10
  end
11
11
 
12
12
  def read(hash, as)
13
+ return FragmentNotFound unless hash
13
14
  hash.has_key?(as) ? hash[as] : FragmentNotFound
14
15
  end
15
16
 
@@ -6,6 +6,18 @@ require "representable"
6
6
  module Representable
7
7
  # Brings #to_json and #from_json to your object.
8
8
  module JSON
9
+ if Kernel.const_defined?(:MultiJson) # Ruby 3.0
10
+ module MultiJSON
11
+ def self.generate(*args)
12
+ MultiJson.dump(*args)
13
+ end
14
+
15
+ def self.parse(*args)
16
+ MultiJson.load(*args)
17
+ end
18
+ end
19
+ end
20
+
9
21
  autoload :Collection, "representable/json/collection"
10
22
 
11
23
  extend Hash::ClassMethods
@@ -33,13 +45,13 @@ module Representable
33
45
 
34
46
  # Parses the body as JSON and delegates to #from_hash.
35
47
  def from_json(data, *args)
36
- data = MultiJson.load(data)
48
+ data = MultiJSON.parse(data)
37
49
  from_hash(data, *args)
38
50
  end
39
51
 
40
52
  # Returns a JSON string representing this object.
41
53
  def to_json(*args)
42
- MultiJson.dump to_hash(*args)
54
+ MultiJSON.generate to_hash(*args)
43
55
  end
44
56
 
45
57
  alias_method :render, :to_json
@@ -1,3 +1,3 @@
1
1
  module Representable
2
- VERSION = "3.1.1"
2
+ VERSION = "3.3.0"
3
3
  end
@@ -2,13 +2,6 @@ require 'representable/binding'
2
2
 
3
3
  module Representable
4
4
  module XML
5
- module_function def Node(document, name, attributes={})
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.
7
-
8
- attributes.each { |k, v| node[k] = v } # TODO: benchmark.
9
- node
10
- end
11
-
12
5
  class Binding < Representable::Binding
13
6
  def self.build_for(definition)
14
7
  return Collection.new(definition) if definition.array?
@@ -24,7 +17,7 @@ module Representable
24
17
  wrap_node = parent
25
18
 
26
19
  if wrap = self[:wrap]
27
- parent << wrap_node = XML::Node(parent, wrap)
20
+ parent << wrap_node = XML::Node(parent.document, wrap)
28
21
  end
29
22
 
30
23
  wrap_node << serialize_for(fragments, parent, as)
@@ -39,7 +32,7 @@ module Representable
39
32
 
40
33
  # Creates wrapped node for the property.
41
34
  def serialize_for(value, parent, as)
42
- node = XML::Node(parent, as) # node doesn't have attr="" attributes!!!
35
+ node = XML::Node(parent.document, as) # node doesn't have attr="" attributes!!!
43
36
  serialize_node(node, value, as)
44
37
  end
45
38
 
@@ -106,7 +99,7 @@ module Representable
106
99
  class Hash < Collection
107
100
  def serialize_for(value, parent, as)
108
101
  set_for(parent, value.collect do |k, v|
109
- node = XML::Node(parent, k)
102
+ node = XML::Node(parent.document, k)
110
103
  serialize_node(node, v, as)
111
104
  end)
112
105
  end
@@ -9,6 +9,13 @@ module Representable
9
9
  autoload :Collection, 'representable/xml/collection'
10
10
  autoload :Namespace, 'representable/xml/namespace'
11
11
 
12
+ module_function def Node(document, name, attributes={})
13
+ node = document.create_element(name.to_s)
14
+
15
+ attributes.each { |k, v| node[k] = v } # TODO: benchmark.
16
+ node
17
+ end
18
+
12
19
  def self.included(base)
13
20
  base.class_eval do
14
21
  include Representable
@@ -19,16 +19,14 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
  spec.license = "MIT"
21
21
 
22
- spec.required_ruby_version = '>= 2.4.0'
22
+ spec.required_ruby_version = '>= 3.0.0'
23
23
 
24
24
  spec.add_dependency "uber", "< 0.2.0"
25
25
  spec.add_dependency "declarative", "< 0.1.0"
26
26
  spec.add_dependency "trailblazer-option", ">= 0.1.1", "< 0.2.0"
27
27
 
28
28
  spec.add_development_dependency "rake"
29
- spec.add_development_dependency "test_xml", ">= 0.1.6"
30
29
  spec.add_development_dependency "minitest"
31
- spec.add_development_dependency "virtus"
32
30
  spec.add_development_dependency "dry-types"
33
31
  spec.add_development_dependency "ruby-prof" if RUBY_ENGINE == "ruby" # mri
34
32
  end
data/test/as_test.rb CHANGED
@@ -1,16 +1,14 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
- class AsTest < MiniTest::Spec
3
+ class AsTest < Minitest::Spec
4
4
  for_formats(
5
- :hash => [Representable::Hash, {"title" => "Wie Es Geht"}, {"title" => "Revolution"}],
5
+ :hash => [Representable::Hash, {"title" => "Wie Es Geht"}, {"title" => "Revolution"}]
6
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
7
  # :yaml => [Representable::YAML, "---\nsong:\n name: Alive\n", "---\nsong:\n name: You've Taken Everything\n"],
8
8
  ) do |format, mod, input, output|
9
-
10
9
  let(:song) { representer.prepare(Song.new("Revolution")) }
11
10
  let(:format) { format }
12
11
 
13
-
14
12
  describe "as: with :symbol" do
15
13
  representer!(:module => mod) do
16
14
  property :name, :as => :title
@@ -20,32 +18,29 @@ class AsTest < MiniTest::Spec
20
18
  it { _(parse(song, input).name).must_equal "Wie Es Geht" }
21
19
  end
22
20
 
23
-
24
21
  describe "as: with lambda" do
25
22
  representer!(:module => mod) do
26
- property :name, :as => lambda { |*| "#{self.class}" }
23
+ property :name, :as => ->(*) { self.class.to_s }
27
24
  end
28
25
 
29
26
  it { render(song).must_equal_document({"Song" => "Revolution"}) }
30
27
  it { _(parse(song, {"Song" => "Wie Es Geht"}).name).must_equal "Wie Es Geht" }
31
28
  end
32
29
 
33
-
34
30
  describe "lambda arguments" do
35
31
  representer! do
36
- property :name, :as => lambda { |options| options[:user_options].inspect }
32
+ property :name, :as => ->(options) { options[:user_options].inspect }
37
33
  end
38
34
 
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" }
35
+ it { render(song, user_options: {volume: 1}).must_equal_document({{volume: 1}.inspect => "Revolution"}) }
36
+ it { _(parse(song, {{volume: 1}.inspect => "Wie Es Geht"}, user_options: {volume: 1}).name).must_equal "Wie Es Geht" }
41
37
  end
42
38
  end
43
39
  end
44
40
 
45
-
46
41
  # hash: to_hash(wrap: ) is representation_wrap
47
42
 
48
- class AsXmlTest < MiniTest::Spec
43
+ class AsXmlTest < Minitest::Spec
49
44
  Band = Struct.new(:name, :label)
50
45
  Album = Struct.new(:band)
51
46
  Label = Struct.new(:name)
data/test/benchmarking.rb CHANGED
@@ -1,11 +1,10 @@
1
- require 'test_helper'
2
- require 'benchmark'
1
+ require "test_helper"
2
+ require "benchmark"
3
3
 
4
4
  SONG_PROPERTIES = 1000.times.collect do |i|
5
5
  "property_#{i}"
6
6
  end
7
7
 
8
-
9
8
  module SongRepresenter
10
9
  include Representable::JSON
11
10
 
@@ -26,7 +25,7 @@ module AlbumRepresenter
26
25
  end
27
26
 
28
27
  def random_song
29
- attrs = Hash[SONG_PROPERTIES.collect { |n| [n,n] }]
28
+ attrs = Hash[SONG_PROPERTIES.collect { |n| [n, n] }]
30
29
  OpenStruct.new(attrs)
31
30
  end
32
31
 
@@ -49,30 +48,26 @@ puts times.join("")
49
48
  ## 100 songs, 1000 attrs
50
49
  # 0.470000 0.010000 0.480000 ( 0.483708)
51
50
 
52
-
53
51
  ### without binding cache:
54
- # 2.790000 0.030000 2.820000 ( 2.820190)
55
-
56
-
52
+ # 2.790000 0.030000 2.820000 ( 2.820190)
57
53
 
58
54
  ### with extend: on Song, with binding cache>
59
- # 2.490000 0.030000 2.520000 ( 2.517433) 2.4-3.0
60
- ### without skip?
61
- # 2.030000 0.020000 2.050000 ( 2.050796) 2.1-2.3
62
-
63
- ### without :writer
64
- # 2.270000 0.010000 2.280000 ( 2.284530 1.9-2.2
65
- ### without :render_filter
66
- # 2.020000 0.000000 2.020000 ( 2.030234) 1.5-2.0
67
- ###without default_for and skipable?
68
- # 1.730000 0.010000 1.740000 ( 1.735597 1.4-1.7
69
- ### without :serialize
70
- # 1.780000 0.010000 1.790000 ( 1.786791) 1.4-1.7
71
- ### using decorator
72
- # 1.400000 0.030000 1.430000 ( 1.434206) 1.4-1.6
73
- ### with prepare AFTER representable?
74
- # 1.330000 0.010000 1.340000 ( 1.335900) 1.1-1.3
75
-
55
+ # 2.490000 0.030000 2.520000 ( 2.517433) 2.4-3.0
56
+ ### without skip?
57
+ # 2.030000 0.020000 2.050000 ( 2.050796) 2.1-2.3
58
+
59
+ ### without :writer
60
+ # 2.270000 0.010000 2.280000 ( 2.284530 1.9-2.2
61
+ ### without :render_filter
62
+ # 2.020000 0.000000 2.020000 ( 2.030234) 1.5-2.0
63
+ # ##without default_for and skipable?
64
+ # 1.730000 0.010000 1.740000 ( 1.735597 1.4-1.7
65
+ ### without :serialize
66
+ # 1.780000 0.010000 1.790000 ( 1.786791) 1.4-1.7
67
+ ### using decorator
68
+ # 1.400000 0.030000 1.430000 ( 1.434206) 1.4-1.6
69
+ ### with prepare AFTER representable?
70
+ # 1.330000 0.010000 1.340000 ( 1.335900) 1.1-1.3
76
71
 
77
72
  # representable 2.0
78
73
  # 3.000000 0.020000 3.020000 ( 3.013031) 2.7-3.0
data/test/binding_test.rb CHANGED
@@ -1,6 +1,6 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
- class BindingTest < MiniTest::Spec
3
+ class BindingTest < Minitest::Spec
4
4
  Binding = Representable::Binding
5
5
  let(:render_nil_definition) { Representable::Definition.new(:song, :render_nil => true) }
6
6
 
@@ -20,7 +20,6 @@ class BindingTest < MiniTest::Spec
20
20
  it { _(Binding.new(Representable::Definition.new(:song)).skipable_empty_value?("Fatal Flu")).must_equal false }
21
21
  end
22
22
 
23
-
24
23
  describe "#default_for" do
25
24
  let(:definition) { Representable::Definition.new(:song, :default => "Insider") }
26
25
  let(:binding) { Binding.new(definition) }
@@ -38,9 +37,18 @@ class BindingTest < MiniTest::Spec
38
37
  it { _(Binding.new(render_nil_definition).default_for(nil)).must_be_nil }
39
38
 
40
39
  # 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 }
40
+ it {
41
+ _(
42
+ Binding.new(
43
+ Representable::Definition.new(
44
+ :song, :render_nil => true,
45
+ :default => "The Quest"
46
+ )
47
+ ).default_for(nil)
48
+ ).must_be_nil
49
+ }
42
50
 
43
51
  # return nil if no :default
44
52
  it { _(Binding.new(Representable::Definition.new(:song)).default_for(nil)).must_be_nil }
45
53
  end
46
- end
54
+ end
data/test/cached_test.rb CHANGED
@@ -1,30 +1,36 @@
1
1
  require "test_helper"
2
2
 
3
3
  class Profiler
4
+ SUPPORTED_ENGINES = %w[ruby jruby].freeze
5
+
6
+ def self.available?
7
+ SUPPORTED_ENGINES.include?(RUBY_ENGINE)
8
+ end
9
+
4
10
  def self.profile(&block)
5
11
  case RUBY_ENGINE
6
- when "ruby"
7
- require 'ruby-prof'
8
-
9
- output = StringIO.new
10
- profile_result = RubyProf.profile(&block)
11
- printer = RubyProf::FlatPrinter.new(profile_result)
12
- printer.print(output)
13
- output.string
14
- when "jruby"
15
- require 'jruby/profiler'
16
-
17
- output_stream = java.io.ByteArrayOutputStream.new
18
- print_stream = java.io.PrintStream.new(output_stream)
19
- profile_result = JRuby::Profiler.profile(&block)
20
- printer = JRuby::Profiler::FlatProfilePrinter.new(profile_result)
21
- printer.printProfile(print_stream)
22
- output_stream.toString
12
+ when "ruby"
13
+ require "ruby-prof"
14
+
15
+ output = StringIO.new
16
+ profile_result = RubyProf::Profile.profile(&block)
17
+ printer = RubyProf::FlatPrinter.new(profile_result)
18
+ printer.print(output)
19
+ output.string
20
+ when "jruby"
21
+ require "jruby/profiler"
22
+
23
+ output_stream = java.io.ByteArrayOutputStream.new
24
+ print_stream = java.io.PrintStream.new(output_stream)
25
+ profile_result = JRuby::Profiler.profile(&block)
26
+ printer = JRuby::Profiler::FlatProfilePrinter.new(profile_result)
27
+ printer.printProfile(print_stream)
28
+ output_stream.toString
23
29
  end
24
30
  end
25
31
  end
26
32
 
27
- class CachedTest < MiniTest::Spec
33
+ class CachedTest < Minitest::Spec
28
34
  # TODO: also test with feature(Cached)
29
35
 
30
36
  module Model
@@ -37,7 +43,7 @@ class CachedTest < MiniTest::Spec
37
43
  include Representable::Hash
38
44
  feature Representable::Cached
39
45
 
40
- property :title, render_filter: lambda { |input, options| "#{input}:#{options[:options][:user_options]}" }
46
+ property :title, render_filter: ->(input, options) { "#{input}:#{options[:options][:user_options]}" }
41
47
  property :composer, class: Model::Artist do
42
48
  property :name
43
49
  end
@@ -51,9 +57,13 @@ class CachedTest < MiniTest::Spec
51
57
  collection :songs, decorator: SongRepresenter, class: Model::Song
52
58
  end
53
59
 
54
-
55
60
  describe "serialization" do
56
- let(:album_hash) { {"name"=>"Louder And Even More Dangerous", "songs"=>[{"title"=>"Southbound:{:volume=>10}"}, {"title"=>"Jailbreak:{:volume=>10}"}]} }
61
+ let(:album_hash) do
62
+ {
63
+ "name" => "Louder And Even More Dangerous",
64
+ "songs" => [{"title" => "Southbound:#{{volume: 10}.inspect}"}, {"title" => "Jailbreak:#{{volume: 10}.inspect}"}]
65
+ }
66
+ end
57
67
 
58
68
  let(:song) { Model::Song.new("Jailbreak") }
59
69
  let(:song2) { Model::Song.new("Southbound") }
@@ -64,8 +74,15 @@ class CachedTest < MiniTest::Spec
64
74
  # album2 = Model::Album.new("Louder And Even More Dangerous", [song2, song])
65
75
 
66
76
  # makes sure options are passed correctly.
67
- _(representer.to_hash(user_options: {volume: 9})).must_equal({"name"=>"Live And Dangerous",
68
- "songs"=>[{"title"=>"Jailbreak:{:volume=>9}"}, {"title"=>"Southbound:{:volume=>9}"}, {"title"=>"Emerald:{:volume=>9}"}]}) # called in Deserializer/Serializer
77
+ _(representer.to_hash(user_options: {volume: 9})).must_equal(
78
+ {
79
+ "name" => "Live And Dangerous",
80
+ "songs" => [
81
+ {"title" => "Jailbreak:#{{volume: 9}.inspect}"}, {"title" => "Southbound:#{{volume: 9}.inspect}"},
82
+ {"title" => "Emerald:#{{volume: 9}.inspect}"}
83
+ ]
84
+ }
85
+ ) # called in Deserializer/Serializer
69
86
 
70
87
  # representer becomes reusable as it is stateless.
71
88
  # representer.update!(album2)
@@ -76,6 +93,8 @@ class CachedTest < MiniTest::Spec
76
93
 
77
94
  # profiling
78
95
  it do
96
+ skip "no profiler available for #{RUBY_ENGINE}" unless Profiler.available?
97
+
79
98
  representer.to_hash
80
99
 
81
100
  data = Profiler.profile { representer.to_hash }
@@ -88,30 +107,29 @@ class CachedTest < MiniTest::Spec
88
107
  # - "3 Representable::Decorator.prepare" -> At JRuby
89
108
 
90
109
  # 3 nested decorator is instantiated for 3 Songs, though.
91
- _(data).must_match(/3\s*(<Class::)?Representable::Decorator\>?[\#.]prepare/m)
110
+ _(data).must_match(/3\s*(<Class::)?Representable::Decorator>?[\#.]prepare/m)
92
111
  # no Binding is instantiated at runtime.
93
112
  _(data).wont_match "Representable::Binding#initialize"
94
113
  # 2 mappers for Album, Song
95
114
  # data.must_match "2 Representable::Mapper::Methods#initialize"
96
115
  # title, songs, 3x title, composer
97
- _(data).must_match(/8\s*Representable::Binding[#\.]render_pipeline/m)
116
+ _(data).must_match(/8\s*Representable::Binding[#.]render_pipeline/m)
98
117
  _(data).wont_match "render_functions"
99
118
  _(data).wont_match "Representable::Binding::Factories#render_functions"
100
119
  end
101
120
  end
102
121
 
103
-
104
122
  describe "deserialization" do
105
- let(:album_hash) {
123
+ let(:album_hash) do
106
124
  {
107
- "name"=>"Louder And Even More Dangerous",
108
- "songs"=>[
109
- {"title"=>"Southbound", "composer"=>{"name"=>"Lynott"}},
110
- {"title"=>"Jailbreak", "composer"=>{"name"=>"Phil Lynott"}},
125
+ "name" => "Louder And Even More Dangerous",
126
+ "songs" => [
127
+ {"title" => "Southbound", "composer" => {"name"=>"Lynott"}},
128
+ {"title" => "Jailbreak", "composer" => {"name"=>"Phil Lynott"}},
111
129
  {"title"=>"Emerald"}
112
130
  ]
113
131
  }
114
- }
132
+ end
115
133
 
116
134
  it do
117
135
  album = Model::Album.new
@@ -131,6 +149,8 @@ class CachedTest < MiniTest::Spec
131
149
  end
132
150
 
133
151
  it "xxx" do
152
+ skip "no profiler available for #{RUBY_ENGINE}" unless Profiler.available?
153
+
134
154
  representer = AlbumRepresenter.new(Model::Album.new)
135
155
  representer.from_hash(album_hash)
136
156
 
@@ -139,12 +159,12 @@ class CachedTest < MiniTest::Spec
139
159
  # only 2 nested decorators are instantiated, Song, and Artist.
140
160
  # Didn't like the regexp?
141
161
  # MRI and JRuby has different output formats. See note above.
142
- _(data).must_match(/5\s*(<Class::)?Representable::Decorator>?[#\.]prepare/)
162
+ _(data).must_match(/5\s*(<Class::)?Representable::Decorator>?[#.]prepare/)
143
163
  # a total of 5 properties in the object graph.
144
164
  _(data).wont_match "Representable::Binding#initialize"
145
165
 
146
166
  _(data).wont_match "parse_functions" # no pipeline creation.
147
- _(data).must_match(/10\s*Representable::Binding[#\.]parse_pipeline/)
167
+ _(data).must_match(/10\s*Representable::Binding[#.]parse_pipeline/)
148
168
  # three mappers for Album, Song, composer
149
169
  # data.must_match "3 Representable::Mapper::Methods#initialize"
150
170
  # # 6 deserializers as the songs collection uses 2.
@@ -154,4 +174,4 @@ class CachedTest < MiniTest::Spec
154
174
  # printer.print(STDOUT)
155
175
  end
156
176
  end
157
- end
177
+ end