declarative 0.0.9 → 0.0.10
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 +4 -4
- data/CHANGES.md +15 -0
- data/declarative.gemspec +1 -1
- data/lib/declarative.rb +1 -0
- data/lib/declarative/deep_dup.rb +2 -2
- data/lib/declarative/defaults.rb +22 -19
- data/lib/declarative/definitions.rb +2 -2
- data/lib/declarative/schema.rb +18 -1
- data/lib/declarative/testing.rb +11 -1
- data/lib/declarative/variables.rb +38 -0
- data/lib/declarative/version.rb +1 -1
- data/test/defaults_test.rb +21 -10
- data/test/variables_test.rb +65 -0
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6e5c86877c99e99dfa9ce880df46435218fcc7a0
|
4
|
+
data.tar.gz: e4b808d37b26399bade9158a92040fb882a3c840
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92ec08dc8dcbe1939a657112edc880b977f16e5b786722a0af007f895399d28d9370415f3db81c2c71e5f270f5be6eeaa10d6b0bcf654f64683113ebe76d639a
|
7
|
+
data.tar.gz: e56d957d4b9b29695b861a7e3852cd66aac31f8f3fe0a01dfa343e054a38f6b4c98aa39dcce5f6e61157ac9a055a6d7cee1730ba8f804d003283db611ef280c1
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
# 0.0.10
|
2
|
+
|
3
|
+
* `Defaults.merge!` will now deprecate non-wrapped `Array` values. The following code is no longer valid (but still works).
|
4
|
+
|
5
|
+
defaults.merge!( list: [1,2] )
|
6
|
+
|
7
|
+
Instead, you need to wrap it in a command like `Variables::Append`.
|
8
|
+
|
9
|
+
defaults.merge!( list: Declarative::Variables::Append( [1,2] ) )
|
10
|
+
|
11
|
+
The reason for this change is to allow all kinds of operations with defaults variables, such as merges, overrides, append, prepend, and so on.
|
12
|
+
|
13
|
+
* Introduce `Declarative::Variables.merge` to merge two sets of variables.
|
14
|
+
* `Defaults` now uses `Variables` for merge/overide operations.
|
15
|
+
|
1
16
|
# 0.0.9
|
2
17
|
|
3
18
|
* Removing `uber` dependency.
|
data/declarative.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.email = ["apotonick@gmail.com"]
|
10
10
|
spec.summary = %q{DSL for nested schemas.}
|
11
11
|
spec.description = %q{DSL for nested generic schemas with inheritance and refining.}
|
12
|
-
spec.homepage = ""
|
12
|
+
spec.homepage = "https://github.com/apotonick/declarative"
|
13
13
|
spec.license = "MIT"
|
14
14
|
|
15
15
|
spec.files = `git ls-files -z`.split("\x0")
|
data/lib/declarative.rb
CHANGED
data/lib/declarative/deep_dup.rb
CHANGED
@@ -2,7 +2,7 @@ module Declarative
|
|
2
2
|
class DeepDup
|
3
3
|
def self.call(args)
|
4
4
|
return Array[*dup_items(args)] if args.is_a?(Array)
|
5
|
-
return Hash[dup_items(args)] if args.is_a?(Hash)
|
5
|
+
return ::Hash[dup_items(args)] if args.is_a?(::Hash)
|
6
6
|
args
|
7
7
|
end
|
8
8
|
|
@@ -11,4 +11,4 @@ module Declarative
|
|
11
11
|
arr.to_a.collect { |v| call(v) }
|
12
12
|
end
|
13
13
|
end
|
14
|
-
end
|
14
|
+
end
|
data/lib/declarative/defaults.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
module Declarative
|
2
|
+
# {Defaults} is a mutable DSL object that collects default directives via #merge!.
|
3
|
+
# Internally, it uses {Variables} to implement the merging of defaults.
|
2
4
|
class Defaults
|
3
5
|
def initialize
|
4
6
|
@static_options = {}
|
5
|
-
@dynamic_options = ->(*) {
|
7
|
+
@dynamic_options = ->(*) { {} }
|
6
8
|
end
|
7
9
|
|
8
10
|
# Set default values. Usually called in Schema::defaults.
|
9
11
|
# This can be called multiple times and will "deep-merge" arrays, e.g. `_features: []`.
|
10
12
|
def merge!(hash={}, &block)
|
11
|
-
@static_options
|
12
|
-
|
13
|
+
@static_options = Variables.merge( @static_options, handle_array_and_deprecate(hash) )
|
13
14
|
@dynamic_options = block if block_given?
|
15
|
+
|
14
16
|
self
|
15
17
|
end
|
16
18
|
|
@@ -19,24 +21,25 @@ module Declarative
|
|
19
21
|
# TODO: allow to receive rest of options/block in dynamic block. or, rather, test it as it was already implemented.
|
20
22
|
evaluated_options = @dynamic_options.(name, given_options)
|
21
23
|
|
22
|
-
options =
|
23
|
-
options =
|
24
|
+
options = Variables.merge( @static_options, handle_array_and_deprecate(evaluated_options) )
|
25
|
+
options = Variables.merge( options, handle_array_and_deprecate(given_options) ) # FIXME: given_options is not tested!
|
26
|
+
end
|
27
|
+
|
28
|
+
def handle_array_and_deprecate(variables)
|
29
|
+
wrapped = Defaults.wrap_arrays(variables)
|
30
|
+
|
31
|
+
warn "[Declarative] Defaults#merge! and #call still accept arrays and automatically prepend those. This is now deprecated, you should replace `ary` with `Declarative::Variables::Append(ary)`." if wrapped.any?
|
32
|
+
|
33
|
+
variables.merge(wrapped)
|
24
34
|
end
|
25
35
|
|
26
|
-
#
|
27
|
-
#
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
a[k] = v and next unless a.has_key?(k)
|
34
|
-
a[k] = v and next unless a[k].is_a?(Array)
|
35
|
-
a[k] = a[k] += v # only for arrays.
|
36
|
-
end
|
37
|
-
|
38
|
-
a
|
39
|
-
end
|
36
|
+
# Wrap arrays in `variables` with Variables::Append so they get appended to existing
|
37
|
+
# same-named arrays.
|
38
|
+
def self.wrap_arrays(variables)
|
39
|
+
Hash[ variables.
|
40
|
+
find_all { |k,v| v.instance_of?(Array) }.
|
41
|
+
collect { |k,v| [k, Variables::Append(v)] }
|
42
|
+
]
|
40
43
|
end
|
41
44
|
end
|
42
45
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Declarative
|
2
|
-
class Definitions < Hash
|
2
|
+
class Definitions < ::Hash
|
3
3
|
class Definition
|
4
4
|
def initialize(name, options={}, &block)
|
5
5
|
@options = options.dup
|
@@ -71,4 +71,4 @@ module Declarative
|
|
71
71
|
options[:_nested_builder].(options)
|
72
72
|
end
|
73
73
|
end
|
74
|
-
end
|
74
|
+
end
|
data/lib/declarative/schema.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "declarative/definitions"
|
2
2
|
require "declarative/defaults"
|
3
|
+
require "declarative/variables"
|
3
4
|
require "declarative/heritage"
|
4
5
|
|
5
6
|
module Declarative
|
@@ -27,6 +28,10 @@ module Declarative
|
|
27
28
|
def defaults(options={}, &block)
|
28
29
|
heritage.record(:defaults, options, &block)
|
29
30
|
|
31
|
+
# Always convert arrays to Variables::Append instructions.
|
32
|
+
options = options.merge( Defaults.wrap_arrays(options) )
|
33
|
+
block = wrap_arrays_from_block(block) if block_given?
|
34
|
+
|
30
35
|
_defaults.merge!(options, &block)
|
31
36
|
end
|
32
37
|
|
@@ -45,6 +50,8 @@ module Declarative
|
|
45
50
|
default_options[:_defaults] = _defaults
|
46
51
|
default_options[:_nested_builder] = nested_builder if block
|
47
52
|
|
53
|
+
# options = options.merge( Defaults.wrap_arrays(options) )
|
54
|
+
|
48
55
|
definitions.add(name, default_options.merge(options), &block)
|
49
56
|
end
|
50
57
|
|
@@ -62,6 +69,16 @@ module Declarative
|
|
62
69
|
class_eval(&options[:_block])
|
63
70
|
end
|
64
71
|
end
|
72
|
+
|
73
|
+
# When called, executes `block` and wraps all array values in Variables::Append.
|
74
|
+
# This is the default behavior in older versions and allows to provide arrays for
|
75
|
+
# default values that will be prepended.
|
76
|
+
def wrap_arrays_from_block(block)
|
77
|
+
->(*args) {
|
78
|
+
options = block.(*args)
|
79
|
+
options.merge( Defaults.wrap_arrays( options ) )
|
80
|
+
}
|
81
|
+
end
|
65
82
|
end
|
66
83
|
|
67
84
|
module Feature
|
@@ -78,7 +95,7 @@ module Declarative
|
|
78
95
|
def register_feature(mod)
|
79
96
|
heritage.record(:register_feature, mod) # this is only for inheritance between decorators and modules!!! ("horizontal and vertical")
|
80
97
|
|
81
|
-
defaults.merge!(_features: [mod])
|
98
|
+
defaults.merge!( _features: Variables::Append([mod]) )
|
82
99
|
end
|
83
100
|
end
|
84
101
|
end
|
data/lib/declarative/testing.rb
CHANGED
@@ -1,4 +1,14 @@
|
|
1
1
|
module Declarative
|
2
|
+
def self.Inspect(obj)
|
3
|
+
string = obj.inspect
|
4
|
+
|
5
|
+
if obj.is_a?(Proc)
|
6
|
+
elements = string.split("/")
|
7
|
+
string = "#{elements.first}#{elements.last}"
|
8
|
+
end
|
9
|
+
string.gsub(/0x\w+/, "")
|
10
|
+
end
|
11
|
+
|
2
12
|
module Inspect
|
3
13
|
def inspect
|
4
14
|
string = super
|
@@ -35,4 +45,4 @@ module Declarative
|
|
35
45
|
super.extend(Declarative::Inspect)
|
36
46
|
end
|
37
47
|
end
|
38
|
-
end
|
48
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Declarative
|
2
|
+
# Implements the pattern of maintaining a hash of key/values (usually "defaults")
|
3
|
+
# that are mutated several times by user and library code (override defaults).
|
4
|
+
#
|
5
|
+
# The Variables instance then represents the configuration data to be processed by the
|
6
|
+
# using library (e.g. Representable or Trailblazer).
|
7
|
+
class Variables
|
8
|
+
class Proc < ::Proc
|
9
|
+
end
|
10
|
+
|
11
|
+
# @return Hash hash where `overrides` is merged onto `defaults` respecting Merge, Append etc.
|
12
|
+
def self.merge(defaults, overrides)
|
13
|
+
defaults = defaults.merge({}) # todo: use our DeepDup. # TODO: or how could we provide immutability?
|
14
|
+
|
15
|
+
overrides.each do |k, v|
|
16
|
+
if v.is_a?(Variables::Proc)
|
17
|
+
defaults[k] = v.( defaults[k] )
|
18
|
+
else
|
19
|
+
defaults[k] = v
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
defaults
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.Merge(merged_hash)
|
27
|
+
Variables::Proc.new do |original|
|
28
|
+
(original || {}).merge( merged_hash )
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.Append(appended_array)
|
33
|
+
Variables::Proc.new do |original|
|
34
|
+
(original || []) + appended_array
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end # Variables
|
38
|
+
end
|
data/lib/declarative/version.rb
CHANGED
data/test/defaults_test.rb
CHANGED
@@ -63,26 +63,37 @@ class DefaultsOptionsTest < Minitest::Spec
|
|
63
63
|
describe "multiple Defaults#merge!" do
|
64
64
|
it "merges arrays automatically" do
|
65
65
|
defaults.merge!(a: 1, b: 2)
|
66
|
-
defaults.merge!( b: 3, _features: ["A"])
|
67
|
-
defaults.merge!( _features: ["B", "C"])
|
66
|
+
defaults.merge!( b: 3, _features: Declarative::Variables::Append(["A"]) )
|
67
|
+
defaults.merge!( _features: Declarative::Variables::Append(["B", "C"]) )
|
68
68
|
defaults.(nil, {}).inspect.must_equal "{:a=>1, :b=>3, :_features=>[\"A\", \"B\", \"C\"]}"
|
69
69
|
end
|
70
70
|
|
71
71
|
it "what" do
|
72
|
-
defaults.merge!(_features: ["A"]) do |name, options|
|
73
|
-
{ _features: ["B", "D"] }
|
72
|
+
defaults.merge!( _features: Declarative::Variables::Append(["A"]) ) do |name, options|
|
73
|
+
{ _features: Declarative::Variables::Append( ["B", "D"] ) }
|
74
74
|
end
|
75
75
|
|
76
76
|
defaults.(nil, {}).inspect.must_equal "{:_features=>[\"A\", \"B\", \"D\"]}"
|
77
77
|
end
|
78
78
|
end
|
79
|
-
end
|
80
79
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
80
|
+
describe "deprecation" do
|
81
|
+
require 'stringio'
|
82
|
+
before do
|
83
|
+
@old_stderr = $stderr
|
84
|
+
$stderr = StringIO.new
|
85
|
+
end
|
86
|
+
|
87
|
+
after { $stderr = @old_stderr }
|
88
|
+
|
89
|
+
it "prints deprecation twice" do
|
90
|
+
defaults.merge!( _features: ["A"] ) do |name, options|
|
91
|
+
{ _features: ["B", "D"] }
|
92
|
+
end
|
85
93
|
|
86
|
-
|
94
|
+
defaults.(nil, {}).inspect.must_equal "{:_features=>[\"A\", \"B\", \"D\"]}"
|
95
|
+
|
96
|
+
$stderr.string.must_equal %{[Declarative] Defaults#merge! and #call still accept arrays and automatically prepend those. This is now deprecated, you should replace `ary` with `Declarative::Variables::Append(ary)`.\n}*2
|
97
|
+
end
|
87
98
|
end
|
88
99
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class DSLOptionsTest < Minitest::Spec
|
4
|
+
let(:defaults) { { id: 1, connections: { first: 1, second: 2 }, list: [3] } }
|
5
|
+
|
6
|
+
Variables = Declarative::Variables
|
7
|
+
|
8
|
+
after do
|
9
|
+
Declarative::Inspect(defaults).must_equal %{{:id=>1, :connections=>{:first=>1, :second=>2}, :list=>[3]}}
|
10
|
+
end
|
11
|
+
|
12
|
+
#- Merge
|
13
|
+
it "merges Merge over original" do
|
14
|
+
options = Variables.merge(
|
15
|
+
defaults,
|
16
|
+
connections: Variables::Merge( second: 3, third: 4 )
|
17
|
+
)
|
18
|
+
|
19
|
+
options.must_equal( { id: 1, connections: { first: 1, second: 3, third: 4 }, :list=>[3] } )
|
20
|
+
end
|
21
|
+
|
22
|
+
it "accepts Procs" do
|
23
|
+
options = Variables.merge(
|
24
|
+
defaults,
|
25
|
+
connections: proc = ->(*) { raise }
|
26
|
+
)
|
27
|
+
|
28
|
+
options.must_equal( { id: 1, connections: proc, :list=>[3] } )
|
29
|
+
end
|
30
|
+
|
31
|
+
it "overrides original without Merge" do
|
32
|
+
options = Variables.merge(
|
33
|
+
defaults, connections: { second: 3, third: 4 } )
|
34
|
+
|
35
|
+
options.must_equal( { id: 1, connections: { second: 3, third: 4 }, :list=>[3] } )
|
36
|
+
end
|
37
|
+
|
38
|
+
it "creates new hash if original not existent" do
|
39
|
+
options = Variables.merge(
|
40
|
+
defaults,
|
41
|
+
bla: Variables::Merge( second: 3, third: 4 )
|
42
|
+
)
|
43
|
+
|
44
|
+
options.must_equal( {:id=>1, :connections=>{:first=>1, :second=>2}, :list=>[3], :bla=>{:second=>3, :third=>4}} )
|
45
|
+
end
|
46
|
+
|
47
|
+
#- Append
|
48
|
+
it "appends to Array" do
|
49
|
+
options = Variables.merge(
|
50
|
+
defaults,
|
51
|
+
list: Variables::Append( [3, 4, 5] )
|
52
|
+
)
|
53
|
+
|
54
|
+
options.must_equal( { id: 1, connections: { first: 1, second: 2 }, :list=>[3, 3, 4, 5] } )
|
55
|
+
end
|
56
|
+
|
57
|
+
it "creates new array if original not existent" do
|
58
|
+
options = Variables.merge(
|
59
|
+
defaults,
|
60
|
+
another_list: Variables::Append( [3, 4, 5] )
|
61
|
+
)
|
62
|
+
|
63
|
+
options.must_equal( { id: 1, connections: { first: 1, second: 2 }, :list=>[3], :another_list=>[3, 4, 5] } )
|
64
|
+
end
|
65
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: declarative
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-09-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -74,13 +74,15 @@ files:
|
|
74
74
|
- lib/declarative/heritage.rb
|
75
75
|
- lib/declarative/schema.rb
|
76
76
|
- lib/declarative/testing.rb
|
77
|
+
- lib/declarative/variables.rb
|
77
78
|
- lib/declarative/version.rb
|
78
79
|
- test/defaults_test.rb
|
79
80
|
- test/definitions_test.rb
|
80
81
|
- test/heritage_test.rb
|
81
82
|
- test/schema_test.rb
|
82
83
|
- test/test_helper.rb
|
83
|
-
|
84
|
+
- test/variables_test.rb
|
85
|
+
homepage: https://github.com/apotonick/declarative
|
84
86
|
licenses:
|
85
87
|
- MIT
|
86
88
|
metadata: {}
|
@@ -100,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
102
|
version: '0'
|
101
103
|
requirements: []
|
102
104
|
rubyforge_project:
|
103
|
-
rubygems_version: 2.6.
|
105
|
+
rubygems_version: 2.6.8
|
104
106
|
signing_key:
|
105
107
|
specification_version: 4
|
106
108
|
summary: DSL for nested schemas.
|
@@ -110,3 +112,4 @@ test_files:
|
|
110
112
|
- test/heritage_test.rb
|
111
113
|
- test/schema_test.rb
|
112
114
|
- test/test_helper.rb
|
115
|
+
- test/variables_test.rb
|