declarative 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/declarative.svg)](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
|