declarative 0.0.1 → 0.0.2
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/.travis.yml +8 -0
- data/CHANGES.md +3 -0
- data/README.md +9 -18
- data/Rakefile +7 -0
- data/declarative.gemspec +4 -1
- data/lib/declarative.rb +27 -1
- data/lib/declarative/defaults.rb +31 -0
- data/lib/declarative/definitions.rb +64 -0
- data/lib/declarative/schema.rb +87 -0
- data/lib/declarative/testing.rb +38 -0
- data/lib/declarative/version.rb +1 -1
- data/test/defaults_test.rb +61 -0
- data/test/definitions_test.rb +82 -0
- data/test/heritage_test.rb +17 -0
- data/test/schema_test.rb +78 -0
- data/test/test_helper.rb +5 -0
- metadata +54 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 778527256a4ef370815476115d8ac7b563f30ec6
|
4
|
+
data.tar.gz: 630a578c3c0e63c3a390a2147651e1020c249be2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6759dca249034da2ed5695308e37192a8b5d6f870a1797341617469e8df3de34785853d8b239ef6a233583f1182733719b9ffbc55a52a024fc2edbf6a708057d
|
7
|
+
data.tar.gz: 4ac48558621fe5afa9c003292559c52dce7c37f105165ceb8a3c6cdeee85344f2f8bcb5f1b9a39f88d49153416a3f25a0a4d521048ab33ce28c708a36e5bfa29
|
data/.travis.yml
ADDED
data/CHANGES.md
ADDED
data/README.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
# Declarative
|
2
2
|
|
3
|
-
|
3
|
+
_DSL for nested schemas._
|
4
|
+
|
5
|
+
[](http://badge.fury.io/rb/declarative)
|
6
|
+
|
7
|
+
# Overview
|
8
|
+
|
9
|
+
Declarative allows _declaring_ nested schemas.
|
4
10
|
|
5
11
|
## Installation
|
6
12
|
|
@@ -10,22 +16,7 @@ Add this line to your application's Gemfile:
|
|
10
16
|
gem 'declarative'
|
11
17
|
```
|
12
18
|
|
13
|
-
And then execute:
|
14
|
-
|
15
|
-
$ bundle
|
16
|
-
|
17
|
-
Or install it yourself as:
|
18
|
-
|
19
|
-
$ gem install declarative
|
20
|
-
|
21
|
-
## Usage
|
22
|
-
|
23
|
-
TODO: Write usage instructions here
|
24
19
|
|
25
|
-
##
|
20
|
+
## Copyright
|
26
21
|
|
27
|
-
|
28
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
29
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
30
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
31
|
-
5. Create a new Pull Request
|
22
|
+
* Copyright (c) 2015 Nick Sutterer <apotonick@gmail.com>
|
data/Rakefile
CHANGED
data/declarative.gemspec
CHANGED
@@ -17,6 +17,9 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
spec.
|
20
|
+
spec.add_dependency "uber", ">= 0.0.15"
|
21
|
+
|
21
22
|
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "minitest"
|
24
|
+
spec.add_development_dependency "minitest-line"
|
22
25
|
end
|
data/lib/declarative.rb
CHANGED
@@ -1,5 +1,31 @@
|
|
1
1
|
require "declarative/version"
|
2
|
+
require "declarative/definitions"
|
3
|
+
require "declarative/defaults"
|
4
|
+
require "declarative/schema"
|
2
5
|
|
3
6
|
module Declarative
|
4
|
-
|
7
|
+
module DSL
|
8
|
+
def heritage
|
9
|
+
@heritage ||= Heritage.new
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Inheritance
|
14
|
+
def included(includer)
|
15
|
+
heritage.(includer)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
class Heritage < Array
|
21
|
+
def record(method, name, options=nil, &block)
|
22
|
+
self << {method: method, args: [name, options ? options.dup : nil].compact, block: block} # DISCUSS: options.dup.
|
23
|
+
end
|
24
|
+
|
25
|
+
def call(inheritor)
|
26
|
+
each do |cfg|
|
27
|
+
inheritor.send(cfg[:method], *cfg[:args], &cfg[:block])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
5
31
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "uber/delegates"
|
2
|
+
|
3
|
+
module Declarative
|
4
|
+
class Defaults
|
5
|
+
def initialize
|
6
|
+
@static_options = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def merge!(hash, &block)
|
10
|
+
@static_options.merge!(hash) if hash.any?
|
11
|
+
@dynamic_options = block if block_given?
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
extend Uber::Delegates
|
16
|
+
delegates :@static_options, :[], :[]= # mutuable API!
|
17
|
+
|
18
|
+
# TODO: allow to receive rest of options/block in dynamic block. or, rather, test it as it was already implemented.
|
19
|
+
def call(name, given_options)
|
20
|
+
options = @static_options
|
21
|
+
options = options.merge(dynamic_options(name, given_options))
|
22
|
+
options = options.merge(given_options)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def dynamic_options(name, given_options)
|
27
|
+
return {} if @dynamic_options.nil?
|
28
|
+
@dynamic_options.call(name, given_options)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Declarative
|
2
|
+
class Definitions < Hash
|
3
|
+
class Definition
|
4
|
+
def initialize(name, options={}, &block)
|
5
|
+
@options = options.clone
|
6
|
+
@options[:name] = name.to_s
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :options # TODO: are we gonna keep this?
|
10
|
+
|
11
|
+
def [](name)
|
12
|
+
@options[name]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(definition_class)
|
17
|
+
@definition_class = definition_class
|
18
|
+
super()
|
19
|
+
end
|
20
|
+
|
21
|
+
def each(&block) # TODO : test me!
|
22
|
+
values.each(&block)
|
23
|
+
end
|
24
|
+
|
25
|
+
# #add is high-level behavior for Definitions#[]=.
|
26
|
+
# reserved options:
|
27
|
+
# :_features
|
28
|
+
# :_defaults
|
29
|
+
# :_base
|
30
|
+
def add(name, options={}, &block)
|
31
|
+
options = options[:_defaults].(name, options) if options[:_defaults] # FIXME: pipeline?
|
32
|
+
base = options[:_base]
|
33
|
+
|
34
|
+
if options.delete(:inherit) and parent_property = get(name)
|
35
|
+
base = parent_property[:nested]
|
36
|
+
options = parent_property.options.merge(options) # TODO: Definition#merge
|
37
|
+
end
|
38
|
+
|
39
|
+
if block
|
40
|
+
options[:nested] = build_nested(
|
41
|
+
options.merge(
|
42
|
+
_base: base,
|
43
|
+
_name: name,
|
44
|
+
_block: block,
|
45
|
+
)
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
# clean up, we don't want that stored in the Definition instance.
|
50
|
+
[:_defaults, :_base, :_nested_builder, :_features].each { |key| options.delete(key) }
|
51
|
+
|
52
|
+
self[name.to_s] = @definition_class.new(name, options)
|
53
|
+
end
|
54
|
+
|
55
|
+
def get(name)
|
56
|
+
self[name.to_s]
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
def build_nested(options)
|
61
|
+
nested = options[:_nested_builder].(options)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require "declarative"
|
2
|
+
require "declarative/definitions"
|
3
|
+
require "declarative/defaults"
|
4
|
+
|
5
|
+
module Declarative
|
6
|
+
# Include this to maintain inheritable, nested schemas with ::defaults and
|
7
|
+
# ::feature the way we have it in Representable, Reform, and Disposable.
|
8
|
+
#
|
9
|
+
# The schema with its defnitions will be kept in ::definitions.
|
10
|
+
module Schema
|
11
|
+
module DSL
|
12
|
+
def property(name, options={}, &block)
|
13
|
+
heritage.record(:property, name, options, &block)
|
14
|
+
|
15
|
+
options = {
|
16
|
+
_base: default_nested_class,
|
17
|
+
}.merge(options)
|
18
|
+
|
19
|
+
options[:_nested_builder] = nested_builder if block
|
20
|
+
options[:_defaults] = _defaults
|
21
|
+
|
22
|
+
definitions.add(name, options, &block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def defaults(options={}, &block)
|
26
|
+
heritage.record(:defaults, options, &block)
|
27
|
+
|
28
|
+
_defaults.merge!(options, &block)
|
29
|
+
end
|
30
|
+
|
31
|
+
def definitions
|
32
|
+
@definitions ||= Definitions.new(definition_class)
|
33
|
+
end
|
34
|
+
|
35
|
+
def definition_class # TODO: test me.
|
36
|
+
Definitions::Definition
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def _defaults
|
41
|
+
@defaults ||= Declarative::Defaults.new
|
42
|
+
end
|
43
|
+
|
44
|
+
def nested_builder
|
45
|
+
NestedBuilder
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
module Heritage
|
50
|
+
def heritage
|
51
|
+
@heritage ||= ::Declarative::Heritage.new
|
52
|
+
end
|
53
|
+
|
54
|
+
def inherited(subclass) # DISCUSS: this could be in Decorator? but then we couldn't do B < A(include X) for non-decorators, right?
|
55
|
+
super
|
56
|
+
heritage.(subclass)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
module Feature
|
61
|
+
# features are registered as defaults using _features, which in turn get translated to
|
62
|
+
# Class.new... { feature mod } which makes it recursive in nested schemas.
|
63
|
+
def feature(*mods)
|
64
|
+
mods.each do |mod|
|
65
|
+
include mod
|
66
|
+
register_feature(mod)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
def register_feature(mod)
|
72
|
+
heritage.record(:register_feature, mod) # this is only for inheritance between decorators and modules!!! ("horizontal and vertical")
|
73
|
+
|
74
|
+
defaults[:_features] ||= []
|
75
|
+
defaults[:_features] << mod
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
NestedBuilder = ->(options) do
|
81
|
+
base = Class.new(options[:_base]) do
|
82
|
+
feature *options[:_features]
|
83
|
+
class_eval(&options[:_block])
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Declarative
|
2
|
+
module Inspect
|
3
|
+
def inspect
|
4
|
+
string = super
|
5
|
+
if is_a?(Proc)
|
6
|
+
elements = string.split("/")
|
7
|
+
string = "#{elements.first}#{elements.last}"
|
8
|
+
end
|
9
|
+
string.gsub(/0x\w+/, "")
|
10
|
+
end
|
11
|
+
|
12
|
+
module Schema
|
13
|
+
def inspect
|
14
|
+
definitions.extend(Definitions::Inspect)
|
15
|
+
"Schema: #{definitions.inspect}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Definitions::Inspect
|
21
|
+
def inspect
|
22
|
+
each { |dfn|
|
23
|
+
dfn.extend(Declarative::Inspect)
|
24
|
+
|
25
|
+
if dfn[:nested] && dfn[:nested].is_a?(Declarative::Schema::DSL)
|
26
|
+
dfn[:nested].extend(Declarative::Inspect::Schema)
|
27
|
+
else
|
28
|
+
dfn[:nested].extend(Declarative::Definitions::Inspect) if dfn[:nested]
|
29
|
+
end
|
30
|
+
}
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
34
|
+
def get(*)
|
35
|
+
super.extend(Declarative::Inspect)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/declarative/version.rb
CHANGED
@@ -0,0 +1,61 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class DefaultsOptionsTest < Minitest::Spec
|
4
|
+
let (:song) { Struct.new(:title, :author_name, :song_volume, :description).new("Revolution", "Some author", 20, nil) }
|
5
|
+
let (:schema) { Declarative::Definitions.new(Declarative::Definitions::Definition).extend Declarative::Definitions::Inspect }
|
6
|
+
let (:defaults) { Declarative::Defaults.new }
|
7
|
+
|
8
|
+
describe "hash options combined with dynamic options" do
|
9
|
+
it do
|
10
|
+
defaults.merge!(render_nil: true) do |name|
|
11
|
+
{ as: name.to_s.upcase }
|
12
|
+
end
|
13
|
+
|
14
|
+
schema.add :title, _defaults: defaults
|
15
|
+
schema.add :author_name
|
16
|
+
schema.add :description, _defaults: defaults
|
17
|
+
|
18
|
+
schema.inspect.must_equal '{"title"=>#<Declarative::Definitions::Definition: @options={:render_nil=>true, :as=>"TITLE", :name=>"title"}>, "author_name"=>#<Declarative::Definitions::Definition: @options={:name=>"author_name"}>, "description"=>#<Declarative::Definitions::Definition: @options={:render_nil=>true, :as=>"DESCRIPTION", :name=>"description"}>}'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "with only dynamic property options" do
|
23
|
+
it do
|
24
|
+
defaults.merge!({}) do |name|
|
25
|
+
{ as: name.to_s.upcase }
|
26
|
+
end
|
27
|
+
|
28
|
+
schema.add :title, _defaults: defaults
|
29
|
+
schema.add :author_name
|
30
|
+
schema.add :description, _defaults: defaults
|
31
|
+
|
32
|
+
schema.inspect.must_equal '{"title"=>#<Declarative::Definitions::Definition: @options={:as=>"TITLE", :name=>"title"}>, "author_name"=>#<Declarative::Definitions::Definition: @options={:name=>"author_name"}>, "description"=>#<Declarative::Definitions::Definition: @options={:as=>"DESCRIPTION", :name=>"description"}>}'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "with only hashes" do
|
37
|
+
it do
|
38
|
+
defaults.merge!(render_nil: true)
|
39
|
+
|
40
|
+
schema.add :title, _defaults: defaults
|
41
|
+
schema.add :author_name
|
42
|
+
schema.add :description, _defaults: defaults
|
43
|
+
|
44
|
+
schema.inspect.must_equal '{"title"=>#<Declarative::Definitions::Definition: @options={:render_nil=>true, :name=>"title"}>, "author_name"=>#<Declarative::Definitions::Definition: @options={:name=>"author_name"}>, "description"=>#<Declarative::Definitions::Definition: @options={:render_nil=>true, :name=>"description"}>}'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#add options win" do
|
49
|
+
it do
|
50
|
+
defaults.merge!(render_nil: true) do |name|
|
51
|
+
{ as: name.to_s.upcase }
|
52
|
+
end
|
53
|
+
|
54
|
+
schema.add :title, as: "Title", _defaults: defaults
|
55
|
+
schema.add :author_name
|
56
|
+
schema.add :description, _defaults: defaults
|
57
|
+
|
58
|
+
schema.inspect.must_equal '{"title"=>#<Declarative::Definitions::Definition: @options={:render_nil=>true, :as=>"Title", :name=>"title"}>, "author_name"=>#<Declarative::Definitions::Definition: @options={:name=>"author_name"}>, "description"=>#<Declarative::Definitions::Definition: @options={:render_nil=>true, :as=>"DESCRIPTION", :name=>"description"}>}'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class DefinitionsTest < Minitest::Spec
|
4
|
+
NestedBuilder = ->(options) {
|
5
|
+
base = options[:_base] || Declarative::Definitions.new(Declarative::Definitions::Definition)
|
6
|
+
base.instance_exec(&options[:_block])
|
7
|
+
base
|
8
|
+
}
|
9
|
+
|
10
|
+
let (:schema) { Declarative::Definitions.new(Declarative::Definitions::Definition).extend(Declarative::Definitions::Inspect) }
|
11
|
+
|
12
|
+
it "what" do
|
13
|
+
# #add works with name
|
14
|
+
schema.add :id
|
15
|
+
# get works with symbol
|
16
|
+
schema.get(:id).inspect.must_equal '#<Declarative::Definitions::Definition: @options={:name=>"id"}>'
|
17
|
+
# get works with string
|
18
|
+
schema.get("id").inspect.must_equal '#<Declarative::Definitions::Definition: @options={:name=>"id"}>'
|
19
|
+
|
20
|
+
# #add with name and options
|
21
|
+
schema.add(:id, unique: true)
|
22
|
+
schema.get(:id).inspect.must_equal '#<Declarative::Definitions::Definition: @options={:unique=>true, :name=>"id"}>'
|
23
|
+
|
24
|
+
pp schema
|
25
|
+
end
|
26
|
+
|
27
|
+
it "overwrites old when called twice" do
|
28
|
+
schema.add :id
|
29
|
+
schema.add :id, cool: true
|
30
|
+
schema.inspect.must_equal '{"id"=>#<Declarative::Definitions::Definition: @options={:cool=>true, :name=>"id"}>}'
|
31
|
+
end
|
32
|
+
|
33
|
+
it "#add with block" do
|
34
|
+
schema.add :artist, _nested_builder: NestedBuilder do
|
35
|
+
add :name
|
36
|
+
add :band, _nested_builder: NestedBuilder do
|
37
|
+
add :location
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
schema.inspect.must_equal '{"artist"=>#<Declarative::Definitions::Definition: @options={:nested=>{"name"=>#<Declarative::Definitions::Definition: @options={:name=>"name"}>, "band"=>#<Declarative::Definitions::Definition: @options={:nested=>{"location"=>#<Declarative::Definitions::Definition: @options={:name=>"location"}>}, :name=>"band"}>}, :name=>"artist"}>}'
|
42
|
+
|
43
|
+
pp schema
|
44
|
+
end
|
45
|
+
|
46
|
+
it "#add with :nested instead of block" do
|
47
|
+
nested_schema = Declarative::Definitions.new(Declarative::Definitions::Definition)
|
48
|
+
nested_schema.extend(Declarative::Definitions::Inspect)
|
49
|
+
|
50
|
+
nested_schema.add :name
|
51
|
+
|
52
|
+
schema.add :artist, nested: nested_schema
|
53
|
+
|
54
|
+
schema.inspect.must_equal '{"artist"=>#<Declarative::Definitions::Definition: @options={:nested=>{"name"=>#<Declarative::Definitions::Definition: @options={:name=>"name"}>}, :name=>"artist"}>}'
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
it "#add with inherit: true and block" do
|
59
|
+
schema.add :artist, cool: true, _nested_builder: NestedBuilder do
|
60
|
+
add :name
|
61
|
+
add :band, crazy: nil, _nested_builder: NestedBuilder do
|
62
|
+
add :location
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
schema.add :id, unique: true, value: 1
|
67
|
+
|
68
|
+
schema.add :artist, uncool: false, _nested_builder: NestedBuilder, inherit: true do
|
69
|
+
add :band, normal: false, _nested_builder: NestedBuilder, inherit: true do
|
70
|
+
add :genre
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
schema.add :id, unique: false, inherit: true
|
75
|
+
|
76
|
+
pp schema
|
77
|
+
|
78
|
+
|
79
|
+
schema.inspect.must_equal '{"artist"=>#<Declarative::Definitions::Definition: @options={:cool=>true, :nested=>{"name"=>#<Declarative::Definitions::Definition: @options={:name=>"name"}>, "band"=>#<Declarative::Definitions::Definition: @options={:crazy=>nil, :nested=>{"location"=>#<Declarative::Definitions::Definition: @options={:name=>"location"}>, "genre"=>#<Declarative::Definitions::Definition: @options={:name=>"genre"}>}, :name=>"band", :normal=>false}>}, :name=>"artist", :uncool=>false}>, "id"=>#<Declarative::Definitions::Definition: @options={:unique=>false, :value=>1, :name=>"id"}>}'
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class HeritageTest < Minitest::Spec
|
4
|
+
# #record
|
5
|
+
module RepresenterA
|
6
|
+
extend Declarative::DSL
|
7
|
+
|
8
|
+
# one arg.
|
9
|
+
heritage.record(:representation_wrap=, true)
|
10
|
+
# 2 args.
|
11
|
+
heritage.record(:property, :name, enable: true)
|
12
|
+
# 3 args.
|
13
|
+
heritage.record(:property, :id, {}, &Proc.new{}.extend(Declarative::Inspect))
|
14
|
+
end
|
15
|
+
|
16
|
+
it { RepresenterA.heritage.inspect.must_equal "[{:method=>:representation_wrap=, :args=>[true], :block=>nil}, {:method=>:property, :args=>[:name, {:enable=>true}], :block=>nil}, {:method=>:property, :args=>[:id, {}], :block=>#<Proc:@heritage_test.rb:13>}]" }
|
17
|
+
end
|
data/test/schema_test.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class SchemaTest < Minitest::Spec
|
4
|
+
class Decorator
|
5
|
+
extend Declarative::Schema::DSL
|
6
|
+
extend Declarative::Schema::Feature # TODO: make automatic
|
7
|
+
extend Declarative::Schema::Heritage # TODO: make automatic
|
8
|
+
|
9
|
+
def self.default_nested_class
|
10
|
+
Decorator
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module AddLinks
|
15
|
+
def self.included(includer)
|
16
|
+
super
|
17
|
+
includer.property(:links)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Concrete < Decorator
|
22
|
+
defaults render_nil: true do |name|
|
23
|
+
{ as: name.to_s.upcase }
|
24
|
+
end
|
25
|
+
feature AddLinks
|
26
|
+
|
27
|
+
property :artist, cool: true do
|
28
|
+
property :name
|
29
|
+
property :band, crazy: nil do
|
30
|
+
property :location
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
property :id, unique: true, value: 1
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
it do
|
39
|
+
Concrete.extend(Declarative::Inspect::Schema)
|
40
|
+
Concrete.inspect
|
41
|
+
pp Concrete.definitions.get(:artist).options
|
42
|
+
# pp Concrete.definitions.get(:artist)[:nested].definitions.get(:band)[:nested].definitions
|
43
|
+
Concrete.inspect.gsub(/\s/, "").must_equal 'Schema:{
|
44
|
+
"links"=>#<Declarative::Definitions::Definition:@options={:render_nil=>true,:as=>"LINKS",:name=>"links"}>,
|
45
|
+
"artist"=>#<Declarative::Definitions::Definition:@options={:render_nil=>true,:as=>"ARTIST",:cool=>true,:nested=>Schema:{
|
46
|
+
"links"=>#<Declarative::Definitions::Definition:@options={:name=>"links"}>,
|
47
|
+
"name"=>#<Declarative::Definitions::Definition:@options={:name=>"name"}>,
|
48
|
+
"band"=>#<Declarative::Definitions::Definition:@options={:crazy=>nil,:nested=>Schema:{
|
49
|
+
"links"=>#<Declarative::Definitions::Definition:@options={:name=>"links"}>,
|
50
|
+
"location"=>#<Declarative::Definitions::Definition:@options={:name=>"location"}>},:name=>"band"}>},:name=>"artist"}>,
|
51
|
+
"id"=>#<Declarative::Definitions::Definition:@options={:render_nil=>true,:as=>"ID",:unique=>true,:value=>1,:name=>"id"}>}'.
|
52
|
+
gsub("\n", "").gsub(/\s/, "")
|
53
|
+
end
|
54
|
+
|
55
|
+
class InheritingConcrete < Concrete
|
56
|
+
property :uuid
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
it do
|
61
|
+
InheritingConcrete.extend(Declarative::Inspect::Schema)
|
62
|
+
InheritingConcrete.inspect
|
63
|
+
pp InheritingConcrete.definitions.get(:artist).options
|
64
|
+
# pp InheritingConcrete.definitions.get(:artist)[:nested].definitions.get(:band)[:nested].definitions
|
65
|
+
InheritingConcrete.inspect.gsub(/\s/, "").must_equal 'Schema:{
|
66
|
+
"links"=>#<Declarative::Definitions::Definition:@options={:render_nil=>true,:as=>"LINKS",:name=>"links"}>,
|
67
|
+
"artist"=>#<Declarative::Definitions::Definition:@options={:render_nil=>true,:as=>"ARTIST",:cool=>true,:nested=>Schema:{
|
68
|
+
"links"=>#<Declarative::Definitions::Definition:@options={:name=>"links"}>,
|
69
|
+
"name"=>#<Declarative::Definitions::Definition:@options={:name=>"name"}>,
|
70
|
+
"band"=>#<Declarative::Definitions::Definition:@options={:crazy=>nil,:nested=>Schema:{
|
71
|
+
"links"=>#<Declarative::Definitions::Definition:@options={:name=>"links"}>,
|
72
|
+
"location"=>#<Declarative::Definitions::Definition:@options={:name=>"location"}>},:name=>"band"}>},:name=>"artist"}>,
|
73
|
+
"id"=>#<Declarative::Definitions::Definition:@options={:render_nil=>true,:as=>"ID",:unique=>true,:value=>1,:name=>"id"}>,
|
74
|
+
"uuid"=>#<Declarative::Definitions::Definition:@options={:render_nil=>true,:as=>"UUID",:name=>"uuid"}>}
|
75
|
+
'.
|
76
|
+
gsub("\n", "").gsub(/\s/, "")
|
77
|
+
end
|
78
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
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.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-10-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: uber
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
20
|
-
type: :
|
19
|
+
version: 0.0.15
|
20
|
+
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 0.0.15
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +38,34 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest-line
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
41
69
|
description: DSL for nested generic schemas with inheritance and refining.
|
42
70
|
email:
|
43
71
|
- apotonick@gmail.com
|
@@ -46,13 +74,24 @@ extensions: []
|
|
46
74
|
extra_rdoc_files: []
|
47
75
|
files:
|
48
76
|
- ".gitignore"
|
77
|
+
- ".travis.yml"
|
78
|
+
- CHANGES.md
|
49
79
|
- Gemfile
|
50
80
|
- LICENSE.txt
|
51
81
|
- README.md
|
52
82
|
- Rakefile
|
53
83
|
- declarative.gemspec
|
54
84
|
- lib/declarative.rb
|
85
|
+
- lib/declarative/defaults.rb
|
86
|
+
- lib/declarative/definitions.rb
|
87
|
+
- lib/declarative/schema.rb
|
88
|
+
- lib/declarative/testing.rb
|
55
89
|
- lib/declarative/version.rb
|
90
|
+
- test/defaults_test.rb
|
91
|
+
- test/definitions_test.rb
|
92
|
+
- test/heritage_test.rb
|
93
|
+
- test/schema_test.rb
|
94
|
+
- test/test_helper.rb
|
56
95
|
homepage: ''
|
57
96
|
licenses:
|
58
97
|
- MIT
|
@@ -73,8 +112,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
112
|
version: '0'
|
74
113
|
requirements: []
|
75
114
|
rubyforge_project:
|
76
|
-
rubygems_version: 2.
|
115
|
+
rubygems_version: 2.4.8
|
77
116
|
signing_key:
|
78
117
|
specification_version: 4
|
79
118
|
summary: DSL for nested schemas.
|
80
|
-
test_files:
|
119
|
+
test_files:
|
120
|
+
- test/defaults_test.rb
|
121
|
+
- test/definitions_test.rb
|
122
|
+
- test/heritage_test.rb
|
123
|
+
- test/schema_test.rb
|
124
|
+
- test/test_helper.rb
|