ditto 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/ditto +1 -1
- data/features/create_entities.feature +1 -0
- data/features/load_entity.feature +1 -0
- data/features/store_entity.feature +5 -4
- data/lib/ditto.rb +1 -0
- data/lib/ditto/dsl.rb +14 -9
- data/lib/ditto/entity.rb +118 -106
- data/lib/ditto/error.rb +19 -0
- data/lib/ditto/options.rb +45 -13
- data/lib/ditto/runner.rb +37 -56
- data/lib/ditto/version.rb +1 -1
- data/spec/entity_spec.rb +83 -59
- data/spec/fixtures/badmap.ditto +18 -0
- data/spec/fixtures/badver.ditto +17 -0
- data/spec/fixtures/bigcircle.ditto +17 -0
- data/spec/fixtures/circle.ditto +16 -0
- data/spec/fixtures/continent.ditto +16 -0
- data/spec/fixtures/country.ditto +16 -0
- data/spec/fixtures/currency.ditto +30 -0
- data/spec/fixtures/currency_group.ditto +17 -0
- data/spec/fixtures/dot.ditto +17 -0
- data/spec/fixtures/dupversion.ditto +32 -0
- data/spec/fixtures/good.ditto +17 -0
- data/spec/fixtures/multiversion.ditto +32 -0
- data/spec/fixtures/nocomma.ditto +16 -0
- data/spec/fixtures/nomethod.ditto +18 -0
- data/spec/fixtures/random.ditto +17 -0
- data/spec/fixtures/syntax.ditto +19 -0
- data/spec/options_spec.rb +43 -25
- data/test/data/simple_object.xml +23 -0
- data/test/data/simple_object.yaml +39 -0
- data/test/ditto/currency.ditto +30 -0
- data/test/ditto/currency_group.ditto +17 -0
- data/test/dm/currency-1.0.0.dm +13 -0
- data/test/dm/currency_group-1.0.0.dm +10 -0
- data/test/dm/datamart-1.0 +7 -0
- data/test/dm/nested +2 -0
- data/test/dmtest.rb +41 -0
- data/test/sample.test +2 -0
- metadata +59 -42
- data/lib/ditto/map.rb +0 -39
@@ -0,0 +1,17 @@
|
|
1
|
+
# Ditto entity definitions and mappings for dot
|
2
|
+
# A circular dependency with bigcircle
|
3
|
+
#
|
4
|
+
|
5
|
+
entity :dot, '1.0.0', {
|
6
|
+
code: [ :mandatory, :unique ],
|
7
|
+
description: nil,
|
8
|
+
bigcircle: :related
|
9
|
+
},
|
10
|
+
add(Dot: '~>1.0') { |ditto|
|
11
|
+
Dot.create(
|
12
|
+
:code => ditto.code,
|
13
|
+
:description => ditto.description,
|
14
|
+
:bigcircle => ditto.bigcircle
|
15
|
+
)
|
16
|
+
}
|
17
|
+
# vim: set ft=ruby:
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Duplicate version entity definition file
|
2
|
+
#
|
3
|
+
|
4
|
+
entity :currency_group, '1.0.0', {
|
5
|
+
:code => [ :mandatory, :unique ],
|
6
|
+
:description => nil,
|
7
|
+
:is_commodity => nil
|
8
|
+
},
|
9
|
+
add(CurrencyGroup: '=1.0.0') { |ditto|
|
10
|
+
CurrencyGroup.create(
|
11
|
+
:code => ditto.code,
|
12
|
+
:description => ditto.description,
|
13
|
+
:is_commodity => ditto.is_commodity
|
14
|
+
)
|
15
|
+
}
|
16
|
+
|
17
|
+
entity :currency_group, '1.0.0', {
|
18
|
+
:code => [ :mandatory, :unique ],
|
19
|
+
:description => nil,
|
20
|
+
:continent => nil,
|
21
|
+
:is_commodity => nil
|
22
|
+
},
|
23
|
+
add(CurrencyGroup: '=2.0.0') { |ditto|
|
24
|
+
CurrencyGroup.create(
|
25
|
+
:code => ditto.code,
|
26
|
+
:description => ditto.description,
|
27
|
+
:continent => ditto.continent,
|
28
|
+
:is_commodity => ditto.is_commodity
|
29
|
+
)
|
30
|
+
}
|
31
|
+
|
32
|
+
# vim: set ft=ruby:
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Correct simple ditto entity definition file
|
2
|
+
#
|
3
|
+
|
4
|
+
entity :currency_group, '1.0.0', {
|
5
|
+
:code => [ :mandatory, :unique ],
|
6
|
+
:description => nil,
|
7
|
+
:is_commodity => nil
|
8
|
+
},
|
9
|
+
add(CurrencyGroup: '=1.0.0') { |ditto|
|
10
|
+
CurrencyGroup.create(
|
11
|
+
:code => ditto.code,
|
12
|
+
:description => ditto.description,
|
13
|
+
:is_commodity => ditto.is_commodity
|
14
|
+
)
|
15
|
+
}
|
16
|
+
|
17
|
+
# vim: set ft=ruby:
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Correct multiple version entity definition
|
2
|
+
#
|
3
|
+
|
4
|
+
entity :currency_group, '1.0.0', {
|
5
|
+
:code => [ :mandatory, :unique ],
|
6
|
+
:description => nil,
|
7
|
+
:is_commodity => nil
|
8
|
+
},
|
9
|
+
add(CurrencyGroup: '=1.0.0') { |ditto|
|
10
|
+
CurrencyGroup.create(
|
11
|
+
:code => ditto.code,
|
12
|
+
:description => ditto.description,
|
13
|
+
:is_commodity => ditto.is_commodity
|
14
|
+
)
|
15
|
+
}
|
16
|
+
|
17
|
+
entity :currency_group, '2.0.0', {
|
18
|
+
:code => [ :mandatory, :unique ],
|
19
|
+
:description => nil,
|
20
|
+
:continent => nil,
|
21
|
+
:is_commodity => nil
|
22
|
+
},
|
23
|
+
add(CurrencyGroup: '=2.0.0') { |ditto|
|
24
|
+
CurrencyGroup.create(
|
25
|
+
:code => ditto.code,
|
26
|
+
:description => ditto.description,
|
27
|
+
:continent => ditto.continent,
|
28
|
+
:is_commodity => ditto.is_commodity
|
29
|
+
)
|
30
|
+
}
|
31
|
+
|
32
|
+
# vim: set ft=ruby:
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Missing add method (due to lack of comma)
|
2
|
+
#
|
3
|
+
entity :currency_group, '1.a.0', {
|
4
|
+
:code => [ :mandatory, :unique ],
|
5
|
+
:description => nil,
|
6
|
+
:is_commodity => nil
|
7
|
+
}
|
8
|
+
add(CurrencyGroup: '=1.0.0') { |ditto|
|
9
|
+
CurrencyGroup.create(
|
10
|
+
:code => ditto.code,
|
11
|
+
:description => ditto.description,
|
12
|
+
:is_commodity => ditto.is_commodity
|
13
|
+
)
|
14
|
+
}
|
15
|
+
|
16
|
+
# vim: set ft=ruby:
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Missing method error in a ditto file
|
2
|
+
#
|
3
|
+
zarg
|
4
|
+
|
5
|
+
entity :currency_group, '1.0.0', {
|
6
|
+
:code => [ :mandatory, :unique ],
|
7
|
+
:description => nil,
|
8
|
+
:is_commodity => nil
|
9
|
+
},
|
10
|
+
add(CurrencyGroup: '=1.0.0') { |ditto|
|
11
|
+
CurrencyGroup.create(
|
12
|
+
:code => ditto.code,
|
13
|
+
:description => ditto.description,
|
14
|
+
:is_commodity => ditto.is_commodity
|
15
|
+
)
|
16
|
+
}
|
17
|
+
|
18
|
+
# vim: set ft=ruby:
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Ditto entity definitions and mappings for random
|
2
|
+
# contains a missing relation
|
3
|
+
#
|
4
|
+
|
5
|
+
entity :random, '1.0.0', {
|
6
|
+
code: [ :mandatory, :unique ],
|
7
|
+
description: nil,
|
8
|
+
stealth: :related
|
9
|
+
},
|
10
|
+
add(Random: '~>1.0') { |ditto|
|
11
|
+
Random.create(
|
12
|
+
:code => ditto.code,
|
13
|
+
:description => ditto.description,
|
14
|
+
:stealth => ditto.stealth
|
15
|
+
)
|
16
|
+
}
|
17
|
+
# vim: set ft=ruby:
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Syntax error in a ditto file
|
2
|
+
#
|
3
|
+
|
4
|
+
---+++
|
5
|
+
|
6
|
+
entity :currency_group, '1.0.0', {
|
7
|
+
:code => [ :mandatory, :unique ],
|
8
|
+
:description => nil,
|
9
|
+
:is_commodity => nil
|
10
|
+
},
|
11
|
+
add(CurrencyGroup: '=1.0.0') { |ditto|
|
12
|
+
CurrencyGroup.create(
|
13
|
+
:code => ditto.code,
|
14
|
+
:description => ditto.description,
|
15
|
+
:is_commodity => ditto.is_commodity
|
16
|
+
)
|
17
|
+
}
|
18
|
+
|
19
|
+
# vim: set ft=ruby:
|
data/spec/options_spec.rb
CHANGED
@@ -1,75 +1,93 @@
|
|
1
1
|
require_relative '../lib/ditto/options'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'tmpdir'
|
2
4
|
|
3
5
|
module Ditto
|
4
6
|
describe Options do
|
7
|
+
before(:all) do
|
8
|
+
@tempdir = Dir.tmpdir
|
9
|
+
@file1 = "#{@tempdir}/file1"
|
10
|
+
@file2 = "#{@tempdir}/file2"
|
11
|
+
FileUtils.touch [@file1, @file2]
|
12
|
+
# ENV.delete 'DITTO_MART'
|
13
|
+
end
|
14
|
+
after(:all) do
|
15
|
+
FileUtils.rm_f [@file1, @file2]
|
16
|
+
end
|
5
17
|
context "specifying no options" do
|
6
18
|
it "should return defaults" do
|
7
|
-
opts = Ditto::Options.
|
8
|
-
opts.parse([])
|
19
|
+
opts = Ditto::Options.new([])
|
9
20
|
opts.connstring.should == Ditto::Options::DEFAULTS[:connstring]
|
10
|
-
opts.
|
21
|
+
opts.dittomart.should == Ditto::Options::DEFAULTS[:dittomart]
|
22
|
+
opts.entitydir.should == Ditto::Options::DEFAULTS[:entitydir]
|
11
23
|
opts.verbose.should == 0
|
12
24
|
opts.debug.should be_false
|
13
25
|
opts.droptables.should be_false
|
14
|
-
opts.
|
26
|
+
opts.loadfiles.size.should == 0
|
15
27
|
end
|
16
28
|
it "should return single path" do
|
17
|
-
opts = Ditto::Options.
|
29
|
+
opts = Ditto::Options.new([@file1])
|
18
30
|
opts.connstring.should == Ditto::Options::DEFAULTS[:connstring]
|
19
|
-
opts.
|
31
|
+
opts.dittomart.should == Ditto::Options::DEFAULTS[:dittomart]
|
20
32
|
opts.verbose.should == 0
|
21
33
|
opts.debug.should be_false
|
22
34
|
opts.droptables.should be_false
|
23
|
-
opts.
|
35
|
+
opts.loadfiles.should == [@file1]
|
24
36
|
end
|
25
37
|
end
|
26
|
-
context "specifying a
|
38
|
+
context "specifying a dittomart" do
|
27
39
|
it "should return it" do
|
28
|
-
|
29
|
-
opts
|
30
|
-
opts.modelpath.should == mpath
|
40
|
+
opts = Ditto::Options.new(["-m", @file1])
|
41
|
+
opts.dittomart.should == @file1
|
31
42
|
end
|
32
43
|
end
|
33
|
-
context "specifying a
|
44
|
+
context "specifying a dittomart that doesn't exist" do
|
34
45
|
it "should fail" do
|
35
|
-
mpath = "zz/zz/zz/zz"
|
36
46
|
expect {
|
37
|
-
opts = Ditto::Options.
|
38
|
-
}.to raise_error(
|
47
|
+
opts = Ditto::Options.new(["-m", "zz/zz/zz"])
|
48
|
+
}.to raise_error(Errno::ENOENT)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
context "not specifying a dittomart" do
|
52
|
+
it "should default to the environment" do
|
53
|
+
pending "Can't work out how to set ENV within an rspec test"
|
54
|
+
ENV['DITTO_MART'] = @file1
|
55
|
+
opts = Ditto::Options.new([@file2])
|
56
|
+
opts.dittomart.should == @file1
|
39
57
|
end
|
40
58
|
end
|
41
59
|
context "specifying a connection string" do
|
42
60
|
it "should return it" do
|
43
61
|
mydb = "username/password@//myserver:1521/my.service.com"
|
44
|
-
opts = Ditto::Options.
|
62
|
+
opts = Ditto::Options.new(["-c", "#{mydb}"])
|
45
63
|
opts.connstring.should == mydb
|
46
64
|
end
|
47
65
|
end
|
48
|
-
context "specifying
|
49
|
-
it "should return the
|
50
|
-
opts = Ditto::Options.
|
51
|
-
opts.
|
66
|
+
context "specifying files and no connection string" do
|
67
|
+
it "should return the files" do
|
68
|
+
opts = Ditto::Options.new([@file1, @file2])
|
69
|
+
opts.loadfiles.should == [@file1, @file2]
|
52
70
|
end
|
53
71
|
end
|
54
72
|
context "specifying files and a connection string" do
|
55
73
|
it "should return the files" do
|
56
|
-
opts = Ditto::Options.
|
57
|
-
opts.
|
74
|
+
opts = Ditto::Options.new(["-c", "u/p@//serv:1521/mydb", @file1, @file2])
|
75
|
+
opts.loadfiles.should == [@file1, @file2]
|
58
76
|
end
|
59
77
|
end
|
60
78
|
context "specifying droptables" do
|
61
79
|
it "should set the options" do
|
62
|
-
opts = Ditto::Options.
|
80
|
+
opts = Ditto::Options.new(["--droptables"])
|
63
81
|
opts.droptables.should be_true
|
64
82
|
end
|
65
83
|
end
|
66
84
|
context "specifying verbose" do
|
67
85
|
it "should set verbose flag" do
|
68
|
-
opts = Ditto::Options.
|
86
|
+
opts = Ditto::Options.new(["-v"])
|
69
87
|
opts.verbose.should == 1
|
70
88
|
end
|
71
89
|
it "should set verbose flag twice" do
|
72
|
-
opts = Ditto::Options.
|
90
|
+
opts = Ditto::Options.new(["-vv"])
|
73
91
|
opts.verbose.should == 2
|
74
92
|
end
|
75
93
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
---------------------------------------- DEFINITIONS ----------------------------------------
|
2
|
+
<object_classes>
|
3
|
+
<object name='currency'>
|
4
|
+
<property name='code' mandatory='Y' is_key='Y' />
|
5
|
+
<property name='description'/>
|
6
|
+
<property name='exchange_rate' mandatory='Y' />
|
7
|
+
<property name='is_designated'/>
|
8
|
+
<relation name='currency_group' relation_object='currency_group' relation_type='unique'/>
|
9
|
+
</object>
|
10
|
+
<object name='currency_group'>
|
11
|
+
<property name='code' mandatory='Y' is_key='Y'/>
|
12
|
+
<property name='description'/>
|
13
|
+
<property name='is_commodity'/>
|
14
|
+
</object>
|
15
|
+
</object_classes>
|
16
|
+
|
17
|
+
---------------------------------------- DATA ----------------------------------------
|
18
|
+
<object_instances>
|
19
|
+
<currency code ='GBP' description='Great Britain Pound' exchange_rate='1.5' is_designated='false'>
|
20
|
+
<currency_group code='Europe' />
|
21
|
+
</currency>
|
22
|
+
<currency_group code='Europe' description='European countries' is_commodity='false'/>
|
23
|
+
</object_instances>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# This format has multiple YAML documents:
|
2
|
+
# The first contains version info, date and author etc.
|
3
|
+
# The subsequent are hashes, each being an entity with key the entity name
|
4
|
+
# Note that strings are used as keys and not symbols for user clarity
|
5
|
+
#
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2012-10-13
|
8
|
+
author: Nick Townsend
|
9
|
+
---
|
10
|
+
currency_group:
|
11
|
+
code: Americas
|
12
|
+
description: The Americas
|
13
|
+
is_commodity: true
|
14
|
+
---
|
15
|
+
currency:
|
16
|
+
code: USD
|
17
|
+
description: United States Dollar
|
18
|
+
exchange_rate: 1.0
|
19
|
+
is_designated: false
|
20
|
+
currency_group: Americas
|
21
|
+
---
|
22
|
+
currency_group:
|
23
|
+
code: Europe
|
24
|
+
description: European Countries
|
25
|
+
is_commodity: false
|
26
|
+
---
|
27
|
+
currency:
|
28
|
+
code: GBP
|
29
|
+
description: Pounds Sterling
|
30
|
+
exchange_rate: 1.5
|
31
|
+
is_designated: false
|
32
|
+
currency_group: Europe
|
33
|
+
---
|
34
|
+
currency:
|
35
|
+
code: EUR
|
36
|
+
description: Euro
|
37
|
+
exchange_rate: 1.2
|
38
|
+
is_designated: false
|
39
|
+
currency_group: Europe
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Ditto entity definitions and mappings for currency
|
2
|
+
#
|
3
|
+
|
4
|
+
entity :currency, '1.0.0', {
|
5
|
+
code: [ :mandatory, :unique ],
|
6
|
+
description: nil,
|
7
|
+
exchange_rate: :mandatory,
|
8
|
+
is_designated: nil,
|
9
|
+
currency_group: :related
|
10
|
+
},
|
11
|
+
add(Currency: '~>1.0', CurrencyGroup: '~>1.0') { |ditto|
|
12
|
+
cg = CurrencyGroup.get(ditto.currency_group)
|
13
|
+
cg.currencies.create(
|
14
|
+
:code => ditto.code,
|
15
|
+
:description => ditto.description,
|
16
|
+
:exchange_rate => ditto.exchange_rate,
|
17
|
+
:is_designated => ditto.is_designated
|
18
|
+
)
|
19
|
+
}
|
20
|
+
add(Currency: '~>2.0', CurrencyGroup: '~>2.0') { |ditto|
|
21
|
+
cg = CurrencyGroup.get(ditto.currency_group)
|
22
|
+
cg.currencies.create(
|
23
|
+
:code => ditto.code,
|
24
|
+
:description => ditto.description,
|
25
|
+
:index => 'ghost',
|
26
|
+
:exchange_rate => ditto.exchange_rate,
|
27
|
+
:is_designated => ditto.is_designated
|
28
|
+
)
|
29
|
+
}
|
30
|
+
# vim: set ft=ruby:
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Ditto entity definitions and mappings for currency_group
|
2
|
+
#
|
3
|
+
|
4
|
+
entity :currency_group, '1.0.0', {
|
5
|
+
:code => [ :mandatory, :unique ],
|
6
|
+
:description => nil,
|
7
|
+
:is_commodity => nil
|
8
|
+
},
|
9
|
+
add(CurrencyGroup: '=1.0.0') { |ditto|
|
10
|
+
CurrencyGroup.create(
|
11
|
+
:code => ditto.code,
|
12
|
+
:description => ditto.description,
|
13
|
+
:is_commodity => ditto.is_commodity
|
14
|
+
)
|
15
|
+
}
|
16
|
+
|
17
|
+
# vim: set ft=ruby:
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# This class encapsulates the existing Currency database
|
2
|
+
#
|
3
|
+
class Currency
|
4
|
+
VERSION = '1.0.0'
|
5
|
+
include DataMapper::Resource
|
6
|
+
|
7
|
+
property :code, String, :key => true
|
8
|
+
property :description, Text, :required => true, :lazy => false
|
9
|
+
property :exchange_rate, Float, :default => 0.0
|
10
|
+
property :is_designated, Boolean, :default => false
|
11
|
+
|
12
|
+
belongs_to :currency_group
|
13
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# This class encapsulates the existing Currency Group database
|
2
|
+
#
|
3
|
+
class CurrencyGroup
|
4
|
+
VERSION = '1.0.0'
|
5
|
+
include DataMapper::Resource
|
6
|
+
property :code, String, :key => true
|
7
|
+
property :description, Text, :required => true, :lazy => false
|
8
|
+
property :is_commodity,Boolean, :default => false
|
9
|
+
has n, :currencies
|
10
|
+
end
|