representable 3.0.0 → 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.
- checksums.yaml +5 -5
- data/.github/workflows/ci.yml +23 -0
- data/CHANGES.md +33 -0
- data/Gemfile +4 -12
- data/LICENSE +1 -1
- data/README.md +12 -13
- data/Rakefile +1 -6
- data/TODO +1 -3
- data/TODO-4.0.md +72 -0
- data/lib/representable/binding.rb +32 -12
- data/lib/representable/cached.rb +1 -1
- data/lib/representable/coercion.rb +8 -6
- data/lib/representable/config.rb +13 -3
- data/lib/representable/debug.rb +23 -15
- data/lib/representable/declarative.rb +12 -7
- data/lib/representable/decorator.rb +1 -1
- data/lib/representable/definition.rb +7 -3
- data/lib/representable/deserializer.rb +5 -4
- data/lib/representable/for_collection.rb +1 -1
- data/lib/representable/hash/allow_symbols.rb +9 -11
- data/lib/representable/hash/binding.rb +1 -0
- data/lib/representable/hash/collection.rb +4 -2
- data/lib/representable/hash.rb +9 -2
- data/lib/representable/hash_methods.rb +3 -2
- data/lib/representable/insert.rb +1 -1
- data/lib/representable/json/collection.rb +3 -0
- data/lib/representable/json.rb +8 -7
- data/lib/representable/object/binding.rb +5 -1
- data/lib/representable/object.rb +1 -1
- data/lib/representable/option.rb +19 -0
- data/lib/representable/pipeline.rb +3 -2
- data/lib/representable/pipeline_factories.rb +4 -2
- data/lib/representable/populator.rb +1 -1
- data/lib/representable/represent.rb +1 -0
- data/lib/representable/serializer.rb +3 -2
- data/lib/representable/version.rb +1 -1
- data/lib/representable/xml/binding.rb +19 -13
- data/lib/representable/xml/namespace.rb +122 -0
- data/lib/representable/xml.rb +12 -10
- data/lib/representable/yaml/binding.rb +1 -0
- data/lib/representable/yaml.rb +6 -2
- data/lib/representable.rb +19 -25
- data/representable.gemspec +8 -9
- data/test/as_test.rb +7 -7
- data/test/binding_test.rb +14 -14
- data/test/cached_test.rb +59 -49
- data/test/class_test.rb +9 -9
- data/test/coercion_test.rb +33 -22
- data/test/config/inherit_test.rb +14 -14
- data/test/config_test.rb +20 -20
- data/test/decorator_scope_test.rb +4 -4
- data/test/decorator_test.rb +33 -20
- data/test/default_test.rb +8 -8
- data/test/defaults_options_test.rb +3 -3
- data/test/definition_test.rb +38 -40
- data/test/{example.rb → examples/example.rb} +0 -1
- data/test/examples/object.rb +1 -5
- data/test/exec_context_test.rb +8 -8
- data/test/features_test.rb +6 -6
- data/test/filter_test.rb +8 -8
- data/test/for_collection_test.rb +10 -10
- data/test/generic_test.rb +13 -13
- data/test/getter_setter_test.rb +5 -5
- data/test/hash_bindings_test.rb +1 -1
- data/test/hash_test.rb +45 -23
- data/test/heritage_test.rb +16 -13
- data/test/if_test.rb +9 -9
- data/test/include_exclude_test.rb +14 -14
- data/test/inherit_test.rb +18 -18
- data/test/inline_test.rb +24 -24
- data/test/instance_test.rb +31 -31
- data/test/is_representable_test.rb +10 -10
- data/test/json_test.rb +29 -7
- data/test/lonely_test.rb +31 -31
- data/test/nested_test.rb +13 -13
- data/test/object_test.rb +9 -9
- data/test/option_test.rb +36 -0
- data/test/parse_pipeline_test.rb +3 -5
- data/test/pipeline_test.rb +50 -50
- data/test/populator_test.rb +18 -18
- data/test/prepare_test.rb +4 -4
- data/test/private_options_test.rb +2 -2
- data/test/reader_writer_test.rb +2 -2
- data/test/render_nil_test.rb +2 -2
- data/test/represent_test.rb +14 -14
- data/test/representable_test.rb +34 -36
- data/test/schema_test.rb +8 -11
- data/test/serialize_deserialize_test.rb +2 -2
- data/test/skip_test.rb +14 -14
- data/test/stringify_hash_test.rb +3 -3
- data/test/test_helper.rb +26 -14
- data/test/uncategorized_test.rb +10 -10
- data/test/user_options_test.rb +4 -4
- data/test/wrap_test.rb +19 -19
- data/test/xml_bindings_test.rb +0 -4
- data/test/xml_namespace_test.rb +186 -0
- data/test/xml_test.rb +103 -43
- data/test/yaml_test.rb +51 -26
- metadata +42 -35
- data/.travis.yml +0 -7
- data/lib/representable/TODO.getting_serious +0 -11
- data/lib/representable/autoload.rb +0 -10
- data/test/mongoid_test.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f3a1388b7570e31d62c555a87d6165793e9d095cf1bed18c04cb8cbe86bc2ba2
|
4
|
+
data.tar.gz: 43e418db52478d3d4fc33f505ce86d840fcb666a8abc83e20269bbfab4c53a3a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39e957975d24f76894ef9a7186fff69155525e5f777c120a77e2ecee8a7dcdccee62b2140ed8ab34ebc9de916a9098d9da846e0befda2c90fa32e4a9ff470ecc
|
7
|
+
data.tar.gz: cf309756f2470854283c09bbca25b3200b26ba1702b75e533573382dabd2f33a6f3eeaee963c2cc2bb0ddb9d3bdf026bf7dacba6da3f22f44dc805bc8d1ca505
|
@@ -0,0 +1,23 @@
|
|
1
|
+
name: CI
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches:
|
5
|
+
- master
|
6
|
+
pull_request:
|
7
|
+
branches:
|
8
|
+
- master
|
9
|
+
|
10
|
+
jobs:
|
11
|
+
test:
|
12
|
+
strategy:
|
13
|
+
fail-fast: false
|
14
|
+
matrix:
|
15
|
+
ruby: [2.5, 2.6, 2.7, '3.0', "3.1"]
|
16
|
+
runs-on: ubuntu-latest
|
17
|
+
steps:
|
18
|
+
- uses: actions/checkout@v2
|
19
|
+
- uses: ruby/setup-ruby@v1
|
20
|
+
with:
|
21
|
+
ruby-version: ${{ matrix.ruby }}
|
22
|
+
bundler-cache: true
|
23
|
+
- run: bundle exec rake
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,36 @@
|
|
1
|
+
# 3.2.0
|
2
|
+
* Drop support for Virtus Coercion
|
3
|
+
* Fix deprecation warning with Nokogiri 1.13.0
|
4
|
+
|
5
|
+
# 3.1.1
|
6
|
+
|
7
|
+
* Upgrade `trailblazer-option` to `0.1.1` which supports passing an empty `keyword_arguments`.
|
8
|
+
|
9
|
+
# 3.1.0
|
10
|
+
* Remove circular require
|
11
|
+
* Use Dry-types 1.0.0+ as coercion library
|
12
|
+
* Renamed Coercion to VirtusCoercion to support old codebases
|
13
|
+
* Replace `declarative-option` with [`trailblazer-option`](https://github.com/trailblazer/trailblazer-option)
|
14
|
+
|
15
|
+
# 3.0.4
|
16
|
+
|
17
|
+
* Add proper XML namespace support.
|
18
|
+
* [internal] Replace `XML::Binding#node_for` with function `XML::Node`.
|
19
|
+
|
20
|
+
# 3.0.3
|
21
|
+
|
22
|
+
* Replace `Uber::Option` with the new [`Declarative::Option`](https://github.com/apotonick/declarative-option). This should result in a significant performance boost.
|
23
|
+
|
24
|
+
# 3.0.2
|
25
|
+
|
26
|
+
* Initialize `Config@wrap` to avoid Ruby's warning.
|
27
|
+
* Add `#render` and `#parse` alias methods to all format modules as a generic entry point.
|
28
|
+
* In `GetValue`, use `public_send` now.
|
29
|
+
|
30
|
+
# 3.0.1
|
31
|
+
|
32
|
+
* Loosen `uber` dependency.
|
33
|
+
|
1
34
|
# 3.0.0
|
2
35
|
|
3
36
|
* Removed deprecations from 2.4.
|
data/Gemfile
CHANGED
@@ -1,19 +1,11 @@
|
|
1
|
-
source
|
1
|
+
source "https://rubygems.org"
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
-
platform :rbx do
|
6
|
-
gem "psych"
|
7
|
-
gem "rubysl-irb"
|
8
|
-
gem "json_pure"
|
9
|
-
end
|
10
|
-
|
11
5
|
group :test do
|
12
|
-
gem "nokogiri", require: false
|
13
|
-
gem "multi_json", require: false
|
14
6
|
gem "minitest-line"
|
15
|
-
gem "
|
7
|
+
gem "multi_json", require: false
|
8
|
+
gem "nokogiri", require: false
|
16
9
|
end
|
10
|
+
gem 'pry-byebug'
|
17
11
|
|
18
|
-
# gem "declarative", path: "../declarative"
|
19
|
-
# gem "declarative", github: "apotonick/declarative"
|
data/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2011 -
|
1
|
+
Copyright (c) 2011 - 2021 Nick Sutterer and the roar contributors
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
a copy of this software and associated documentation files (the
|
data/README.md
CHANGED
@@ -2,19 +2,19 @@
|
|
2
2
|
|
3
3
|
Representable maps Ruby objects to documents and back.
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
Status](https://travis-ci.org/apotonick/representable.svg)](https://travis-ci.org/apotonick/representable)
|
5
|
+

|
8
7
|
[](http://badge.fury.io/rb/representable)
|
9
8
|
|
9
|
+
|
10
10
|
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.
|
11
11
|
|
12
|
-
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](
|
12
|
+
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.
|
13
13
|
|
14
14
|
|
15
15
|
## Full Documentation
|
16
16
|
|
17
|
-
Representable comes with a rich set of options and semantics for parsing and rendering documents. Its [full documentation](
|
17
|
+
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.
|
18
18
|
|
19
19
|
## Example
|
20
20
|
|
@@ -34,8 +34,6 @@ Representations are defined using representer classes, called _decorator, or mod
|
|
34
34
|
In these examples, let's use decorators
|
35
35
|
|
36
36
|
```ruby
|
37
|
-
require 'representable/json'
|
38
|
-
|
39
37
|
class SongRepresenter < Representable::Decorator
|
40
38
|
include Representable::JSON
|
41
39
|
|
@@ -65,7 +63,7 @@ song = SongRepresenter.new(song).from_json(%{ {"title":"Roxanne"} })
|
|
65
63
|
#=> #<Song title="Roxanne", track=nil>
|
66
64
|
```
|
67
65
|
|
68
|
-
Note that parsing hashes per default does [require string keys](
|
66
|
+
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.
|
69
67
|
|
70
68
|
|
71
69
|
## Collections
|
@@ -131,19 +129,20 @@ class AlbumRepresenter < Representable::Decorator
|
|
131
129
|
property :track
|
132
130
|
collection :composers
|
133
131
|
end
|
132
|
+
end
|
134
133
|
```
|
135
134
|
|
136
135
|
## More
|
137
136
|
|
138
137
|
Representable has many more features and can literally parse and render any kind of document to an arbitrary Ruby object graph.
|
139
138
|
|
140
|
-
Please check the [official documentation for more](
|
139
|
+
Please check the [official documentation for more](https://trailblazer.to/2.1/docs/representable.html#representable-api).
|
141
140
|
|
142
141
|
|
143
142
|
## Installation
|
144
143
|
|
145
|
-
The representable gem runs with all Ruby versions >=
|
146
|
-
|
144
|
+
The representable gem runs with all Ruby versions >= 2.4.0.
|
145
|
+
t
|
147
146
|
```ruby
|
148
147
|
gem 'representable'
|
149
148
|
```
|
@@ -169,7 +168,7 @@ gem 'nokogiri'
|
|
169
168
|
|
170
169
|
Representable started as a heavily simplified fork of the ROXML gem. Big thanks to Ben Woosley for his extremely inspiring work.
|
171
170
|
|
172
|
-
* Copyright (c) 2011-
|
171
|
+
* Copyright (c) 2011-2020 Nick Sutterer <apotonick@gmail.com>
|
173
172
|
* ROXML is Copyright (c) 2004-2009 Ben Woosley, Zak Mandhro and Anders Engstrom.
|
174
173
|
|
175
|
-
Representable is released under the [MIT License](
|
174
|
+
Representable is released under the [MIT License](https://www.opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
1
2
|
require 'bundler/setup'
|
2
3
|
require 'rake/testtask'
|
3
4
|
|
@@ -9,9 +10,3 @@ Rake::TestTask.new(:test) do |test|
|
|
9
10
|
test.test_files = FileList['test/**/*_test.rb']
|
10
11
|
test.verbose = true
|
11
12
|
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/TODO
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
* Pass key/index as first block arg to :class and :extend
|
2
2
|
class: |key, hsh|
|
3
3
|
|
4
|
-
* Allow passing options to Binding#serialize.
|
5
|
-
serialize(.., options{:exclude => ..})
|
6
4
|
|
7
5
|
document `XML::AttributeHash` etc
|
8
6
|
|
@@ -37,4 +35,4 @@ module ReaderWriter
|
|
37
35
|
* DISCUSS: should inline representers be created at runtime, so we don't need ::representer_engine?
|
38
36
|
* deprecate `Decorator::Coercion`.
|
39
37
|
|
40
|
-
* cleanup XML so it matches the current #serialize standard.
|
38
|
+
* cleanup XML so it matches the current #serialize standard.
|
data/TODO-4.0.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# Decorator
|
2
|
+
|
3
|
+
XML::Binding::Collection.to_xml(represented)
|
4
|
+
bindings.each bin.to_xml
|
5
|
+
|
6
|
+
|
7
|
+
# hat vorteil: [].each{ Collection.to_xml(item) }
|
8
|
+
|
9
|
+
* make all properties "Object-like", even arrays of strings etc. This saves us from having `extend ObjectBinding if typed?` and we could just call to_hash/from_hash on all attributes. performance issues here? otherwise: implement!
|
10
|
+
|
11
|
+
|
12
|
+
# how to?
|
13
|
+
|
14
|
+
class CH
|
15
|
+
wrap :character
|
16
|
+
prpoerty :a
|
17
|
+
|
18
|
+
|
19
|
+
class
|
20
|
+
proerty :author, dec: CH
|
21
|
+
|
22
|
+
# how to?
|
23
|
+
|
24
|
+
* override specific bindings and their logic? e.g. `Namespace#read`
|
25
|
+
* Extend nested representers, e.g. the namespace prefix, when it gets plugged into composition
|
26
|
+
* Easier polymorphic representer
|
27
|
+
|
28
|
+
# XML
|
29
|
+
|
30
|
+
* ditch annoying nokogiri in favor of https://github.com/YorickPeterse/oga
|
31
|
+
|
32
|
+
# Parsing
|
33
|
+
|
34
|
+
* Let bindings have any "xpath"
|
35
|
+
* Allow to parse "wildcard" sections where you have no idea about the property names (and attribute names, eg. with links)
|
36
|
+
|
37
|
+
# Options
|
38
|
+
|
39
|
+
* There should be an easier way to pass a set of options to all nested #to_node decorators.
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
representable_attrs.keys.each do |property|
|
43
|
+
options[property.to_sym] = { show_definition: false, namespaces: options[:namespaces] }
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
* Allow passing options to Binding#serialize.
|
48
|
+
serialize(.., options{:exclude => ..})
|
49
|
+
|
50
|
+
|
51
|
+
# wrap, as
|
52
|
+
|
53
|
+
AsWithNamespace( Binding )
|
54
|
+
BUT NOT FOR AsWithNamespace( Binding::Attribute )
|
55
|
+
=> selectively wrap bindings at compile- and runtime
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
* Cleanup the manifest part in Decorator.
|
63
|
+
|
64
|
+
* all property objects should be extended/wrapped so we don't need the switch.
|
65
|
+
|
66
|
+
# Deprecations
|
67
|
+
|
68
|
+
* deprecate instance: { nil } which is superseded by parse_strategy: :sync
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
from_hash, property :band, class: vergessen
|
@@ -1,8 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'uber/delegates'
|
4
|
+
|
1
5
|
module Representable
|
2
6
|
# The Binding provides methods to read/write the fragment for one property.
|
3
7
|
#
|
4
8
|
# Actually parsing the fragment from the document happens in Binding#read, everything after that is generic.
|
5
9
|
class Binding
|
10
|
+
class Map < Array
|
11
|
+
def call(method, options)
|
12
|
+
each do |bin|
|
13
|
+
options[:binding] = bin # this is so much faster than options.merge().
|
14
|
+
bin.send(method, options)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# TODO: Merge with Definitions.
|
19
|
+
def <<(binding) # can be slow. this is compile time code.
|
20
|
+
(existing = find { |bin| bin.name == binding.name }) ? self[index(existing)] = binding : super(binding)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
6
24
|
class FragmentNotFound
|
7
25
|
end
|
8
26
|
|
@@ -29,12 +47,12 @@ module Representable
|
|
29
47
|
module Deprecatable
|
30
48
|
# Retrieve value and write fragment to the doc.
|
31
49
|
def compile_fragment(options)
|
32
|
-
render_pipeline(nil, options).(nil, options)
|
50
|
+
render_pipeline(nil, options).call(nil, options)
|
33
51
|
end
|
34
52
|
|
35
53
|
# Parse value from doc and update the model property.
|
36
54
|
def uncompile_fragment(options)
|
37
|
-
parse_pipeline(options[:doc], options).(options[:doc], options)
|
55
|
+
parse_pipeline(options[:doc], options).call(options[:doc], options)
|
38
56
|
end
|
39
57
|
end
|
40
58
|
include Deprecatable
|
@@ -43,7 +61,7 @@ module Representable
|
|
43
61
|
def evaluate_option(name, input, options)
|
44
62
|
proc = self[name]
|
45
63
|
# puts "@@@@@ #{self.inspect}, #{name}...... #{self[name]}"
|
46
|
-
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.
|
64
|
+
proc.call(exec_context: send(:exec_context, options), keyword_arguments: 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
65
|
end
|
48
66
|
end
|
49
67
|
include EvaluateOption
|
@@ -53,29 +71,30 @@ module Representable
|
|
53
71
|
end
|
54
72
|
|
55
73
|
def skipable_empty_value?(value)
|
56
|
-
value.nil? and
|
74
|
+
value.nil? and !(self[:render_nil])
|
57
75
|
end
|
58
76
|
|
59
77
|
def default_for(value)
|
60
78
|
return self[:default] if skipable_empty_value?(value)
|
79
|
+
|
61
80
|
value
|
62
81
|
end
|
63
82
|
|
64
83
|
attr_accessor :cached_representer
|
65
84
|
|
66
|
-
require
|
85
|
+
require 'representable/pipeline_factories'
|
67
86
|
include Factories
|
68
87
|
|
69
|
-
|
88
|
+
private
|
70
89
|
|
71
90
|
def setup_exec_context!
|
72
|
-
@exec_context = ->(options) { options[:represented] }
|
73
|
-
@exec_context = ->(
|
74
|
-
@exec_context = ->(options) { options[:decorator] }
|
91
|
+
@exec_context = ->(options) { options[:represented] } unless self[:exec_context]
|
92
|
+
@exec_context = ->(_options) { self } if self[:exec_context] == :binding
|
93
|
+
@exec_context = ->(options) { options[:decorator] } if self[:exec_context] == :decorator
|
75
94
|
end
|
76
95
|
|
77
96
|
def exec_context(options)
|
78
|
-
@exec_context.(options)
|
97
|
+
@exec_context.call(options)
|
79
98
|
end
|
80
99
|
|
81
100
|
def parse_pipeline(input, options)
|
@@ -90,8 +109,9 @@ module Representable
|
|
90
109
|
module Collection
|
91
110
|
def skipable_empty_value?(value)
|
92
111
|
# TODO: this can be optimized, again.
|
93
|
-
return true if value.nil?
|
94
|
-
|
112
|
+
return true if value.nil? && !(self[:render_nil]) # FIXME: test this without the "and"
|
113
|
+
|
114
|
+
true if (self[:render_empty] == false) && value && value.empty? # TODO: change in 2.0, don't render emtpy.
|
95
115
|
end
|
96
116
|
end
|
97
117
|
end
|
data/lib/representable/cached.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
|
-
|
1
|
+
gem 'dry-types', '>= 1.0.0'
|
2
|
+
require "dry-types"
|
2
3
|
|
3
4
|
module Representable
|
4
5
|
module Coercion
|
6
|
+
module Types
|
7
|
+
include Dry::Types()
|
8
|
+
end
|
5
9
|
class Coercer
|
6
10
|
def initialize(type)
|
7
11
|
@type = type
|
8
12
|
end
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
def call(input, options)
|
13
|
-
Virtus::Attribute.build(@type).coerce(input)
|
14
|
+
def call(input, _options)
|
15
|
+
@type.call(input)
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
@@ -34,4 +36,4 @@ module Representable
|
|
34
36
|
end
|
35
37
|
end
|
36
38
|
end
|
37
|
-
end
|
39
|
+
end
|
data/lib/representable/config.rb
CHANGED
@@ -1,10 +1,19 @@
|
|
1
|
+
require 'declarative/definitions'
|
2
|
+
|
1
3
|
module Representable
|
4
|
+
autoload :Option, 'representable/option'
|
5
|
+
|
2
6
|
# Stores Definitions from ::property. It preserves the adding order (1.9+).
|
3
7
|
# Same-named properties get overridden, just like in a Hash.
|
4
8
|
#
|
5
9
|
# Overwrite definition_class if you need a custom Definition object (helpful when using
|
6
10
|
# representable in other gems).
|
7
11
|
class Config < ::Declarative::Definitions
|
12
|
+
def initialize(*)
|
13
|
+
super
|
14
|
+
@wrap = nil
|
15
|
+
end
|
16
|
+
|
8
17
|
def remove(name)
|
9
18
|
delete(name.to_s)
|
10
19
|
end
|
@@ -15,16 +24,17 @@ module Representable
|
|
15
24
|
|
16
25
|
def wrap=(value)
|
17
26
|
value = value.to_s if value.is_a?(Symbol)
|
18
|
-
@wrap =
|
27
|
+
@wrap = ::Representable::Option(value)
|
19
28
|
end
|
20
29
|
|
21
30
|
# Computes the wrap string or returns false.
|
22
|
-
def wrap_for(represented,
|
31
|
+
def wrap_for(represented, options = {}, &block)
|
23
32
|
return unless @wrap
|
24
33
|
|
25
|
-
value = @wrap.
|
34
|
+
value = @wrap.(exec_context: represented, keyword_arguments: options.to_hash)
|
26
35
|
|
27
36
|
return value if value != true
|
37
|
+
|
28
38
|
infer_name_for(represented.class.name)
|
29
39
|
end
|
30
40
|
|
data/lib/representable/debug.rb
CHANGED
@@ -1,16 +1,24 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
1
3
|
module Representable
|
2
4
|
module Debug
|
5
|
+
module_function def _representable_logger
|
6
|
+
@logger ||= Logger.new(STDOUT)
|
7
|
+
end
|
8
|
+
|
9
|
+
module_function def representable_log(message)
|
10
|
+
_representable_logger.debug { message }
|
11
|
+
end
|
12
|
+
|
3
13
|
def update_properties_from(doc, options, format)
|
4
|
-
|
5
|
-
|
6
|
-
puts "[Deserialize] document #{doc.inspect}"
|
14
|
+
representable_log "[Deserialize]........."
|
15
|
+
representable_log "[Deserialize] document #{doc.inspect}"
|
7
16
|
super
|
8
17
|
end
|
9
18
|
|
10
19
|
def create_representation_with(doc, options, format)
|
11
|
-
|
12
|
-
|
13
|
-
puts "[Serialize]"
|
20
|
+
representable_log "[Serialize]........."
|
21
|
+
representable_log "[Serialize]"
|
14
22
|
super
|
15
23
|
end
|
16
24
|
|
@@ -22,13 +30,13 @@ module Representable
|
|
22
30
|
|
23
31
|
module Binding
|
24
32
|
def evaluate_option(name, *args, &block)
|
25
|
-
|
26
|
-
|
33
|
+
Debug.representable_log "=====#{self[name]}" if name ==:prepare
|
34
|
+
Debug.representable_log (evaled = self[name]) ?
|
27
35
|
" #evaluate_option [#{name}]: eval!!!" :
|
28
36
|
" #evaluate_option [#{name}]: skipping"
|
29
37
|
value = super
|
30
|
-
|
31
|
-
|
38
|
+
Debug.representable_log " #evaluate_option [#{name}]: --> #{value}" if evaled
|
39
|
+
Debug.representable_log " #evaluate_option [#{name}]: -->= #{args.first}" if name == :setter
|
32
40
|
value
|
33
41
|
end
|
34
42
|
|
@@ -45,17 +53,17 @@ module Representable
|
|
45
53
|
|
46
54
|
module Pipeline::Debug
|
47
55
|
def call(input, options)
|
48
|
-
|
49
|
-
|
56
|
+
Debug.representable_log "Pipeline#call: #{inspect}"
|
57
|
+
Debug.representable_log " input: #{input.inspect}"
|
50
58
|
super
|
51
59
|
end
|
52
60
|
|
53
61
|
def evaluate(block, memo, options)
|
54
62
|
block.extend(Pipeline::Debug) if block.is_a?(Collect)
|
55
63
|
|
56
|
-
|
64
|
+
Debug.representable_log " Pipeline : -> #{_inspect_function(block)} "
|
57
65
|
super.tap do |res|
|
58
|
-
|
66
|
+
Debug.representable_log " Pipeline : result: #{res.inspect}"
|
59
67
|
end
|
60
68
|
end
|
61
69
|
|
@@ -70,8 +78,8 @@ module Representable
|
|
70
78
|
def _inspect_function(func)
|
71
79
|
return func.extend(Pipeline::Debug).inspect if func.is_a?(Collect)
|
72
80
|
return func unless func.is_a?(Proc)
|
81
|
+
|
73
82
|
File.readlines(func.source_location[0])[func.source_location[1]-1].match(/^\s+(\w+)/)[1]
|
74
83
|
end
|
75
84
|
end
|
76
85
|
end
|
77
|
-
|
@@ -1,4 +1,9 @@
|
|
1
|
+
require "declarative/schema"
|
2
|
+
|
1
3
|
module Representable
|
4
|
+
autoload :Decorator, "representation/decorator"
|
5
|
+
autoload :Definition, "representation/definition"
|
6
|
+
|
2
7
|
module Declarative
|
3
8
|
def representation_wrap=(name)
|
4
9
|
heritage.record(:representation_wrap=, name)
|
@@ -21,9 +26,9 @@ module Representable
|
|
21
26
|
# them to the original object.
|
22
27
|
def nested(name, options={}, &block)
|
23
28
|
options = options.merge(
|
24
|
-
getter: ->(
|
25
|
-
setter: ->(
|
26
|
-
instance: ->(
|
29
|
+
getter: ->(_opts) { self },
|
30
|
+
setter: ->(opts) { },
|
31
|
+
instance: ->(_opts) { self },
|
27
32
|
)
|
28
33
|
|
29
34
|
if block
|
@@ -47,10 +52,10 @@ module Representable
|
|
47
52
|
NestedBuilder = ->(options) do
|
48
53
|
Module.new do
|
49
54
|
include Representable # FIXME: do we really need this?
|
50
|
-
feature
|
51
|
-
include
|
55
|
+
feature(*options[:_features])
|
56
|
+
include(*options[:_base]) # base when :inherit, or in decorator.
|
52
57
|
|
53
|
-
module_eval
|
58
|
+
module_eval(&options[:_block])
|
54
59
|
end
|
55
60
|
end
|
56
61
|
|
@@ -64,4 +69,4 @@ module Representable
|
|
64
69
|
|
65
70
|
alias_method :representable_attrs, :definitions
|
66
71
|
end
|
67
|
-
end
|
72
|
+
end
|
@@ -1,7 +1,10 @@
|
|
1
|
-
require
|
2
|
-
require "representable/populator"
|
1
|
+
require 'declarative/definitions'
|
3
2
|
|
4
3
|
module Representable
|
4
|
+
autoload :Pipeline, "representable/pipeline"
|
5
|
+
autoload :Populator, "representable/populator"
|
6
|
+
autoload :Option, "representable/option"
|
7
|
+
|
5
8
|
# Created at class compile time. Keeps configuration options for one property.
|
6
9
|
class Definition < ::Declarative::Definitions::Definition
|
7
10
|
|
@@ -54,6 +57,7 @@ module Representable
|
|
54
57
|
|
55
58
|
def representable?
|
56
59
|
return if self[:representable] == false
|
60
|
+
|
57
61
|
self[:representable] or typed?
|
58
62
|
end
|
59
63
|
|
@@ -102,7 +106,7 @@ module Representable
|
|
102
106
|
@runtime_options = {}
|
103
107
|
|
104
108
|
for name, value in options
|
105
|
-
value =
|
109
|
+
value = ::Representable::Option(value) if dynamic_options.include?(name)
|
106
110
|
@runtime_options[name] = value
|
107
111
|
end
|
108
112
|
end
|
@@ -11,11 +11,11 @@ module Representable
|
|
11
11
|
ReadFragment = ->(input, options) { options[:binding].read(input, options[:as]) }
|
12
12
|
Reader = ->(input, options) { options[:binding].evaluate_option(:reader, input, options) }
|
13
13
|
|
14
|
-
StopOnNotFound = ->(input,
|
14
|
+
StopOnNotFound = ->(input, _options) do
|
15
15
|
Binding::FragmentNotFound == input ? Pipeline::Stop : input
|
16
16
|
end
|
17
17
|
|
18
|
-
StopOnNil = ->(input,
|
18
|
+
StopOnNil = ->(input, _options) do # DISCUSS: Not tested/used, yet.
|
19
19
|
input.nil? ? Pipeline::Stop : input
|
20
20
|
end
|
21
21
|
|
@@ -96,13 +96,14 @@ module Representable
|
|
96
96
|
If = ->(input, options) { options[:binding].evaluate_option(:if, nil, options) ? input : Pipeline::Stop }
|
97
97
|
|
98
98
|
StopOnExcluded = ->(input, options) do
|
99
|
-
return input unless
|
99
|
+
return input unless options[:options]
|
100
100
|
return input unless props = (options[:options][:exclude] || options[:options][:include])
|
101
101
|
|
102
102
|
res = props.include?(options[:binding].name.to_sym) # false with include: Stop. false with exclude: go!
|
103
103
|
|
104
104
|
return input if options[:options][:include]&&res
|
105
105
|
return input if options[:options][:exclude]&&!res
|
106
|
+
|
106
107
|
Pipeline::Stop
|
107
108
|
end
|
108
|
-
end
|
109
|
+
end
|