ditto 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/bin/ditto +1 -1
  2. data/features/create_entities.feature +1 -0
  3. data/features/load_entity.feature +1 -0
  4. data/features/store_entity.feature +5 -4
  5. data/lib/ditto.rb +1 -0
  6. data/lib/ditto/dsl.rb +14 -9
  7. data/lib/ditto/entity.rb +118 -106
  8. data/lib/ditto/error.rb +19 -0
  9. data/lib/ditto/options.rb +45 -13
  10. data/lib/ditto/runner.rb +37 -56
  11. data/lib/ditto/version.rb +1 -1
  12. data/spec/entity_spec.rb +83 -59
  13. data/spec/fixtures/badmap.ditto +18 -0
  14. data/spec/fixtures/badver.ditto +17 -0
  15. data/spec/fixtures/bigcircle.ditto +17 -0
  16. data/spec/fixtures/circle.ditto +16 -0
  17. data/spec/fixtures/continent.ditto +16 -0
  18. data/spec/fixtures/country.ditto +16 -0
  19. data/spec/fixtures/currency.ditto +30 -0
  20. data/spec/fixtures/currency_group.ditto +17 -0
  21. data/spec/fixtures/dot.ditto +17 -0
  22. data/spec/fixtures/dupversion.ditto +32 -0
  23. data/spec/fixtures/good.ditto +17 -0
  24. data/spec/fixtures/multiversion.ditto +32 -0
  25. data/spec/fixtures/nocomma.ditto +16 -0
  26. data/spec/fixtures/nomethod.ditto +18 -0
  27. data/spec/fixtures/random.ditto +17 -0
  28. data/spec/fixtures/syntax.ditto +19 -0
  29. data/spec/options_spec.rb +43 -25
  30. data/test/data/simple_object.xml +23 -0
  31. data/test/data/simple_object.yaml +39 -0
  32. data/test/ditto/currency.ditto +30 -0
  33. data/test/ditto/currency_group.ditto +17 -0
  34. data/test/dm/currency-1.0.0.dm +13 -0
  35. data/test/dm/currency_group-1.0.0.dm +10 -0
  36. data/test/dm/datamart-1.0 +7 -0
  37. data/test/dm/nested +2 -0
  38. data/test/dmtest.rb +41 -0
  39. data/test/sample.test +2 -0
  40. metadata +59 -42
  41. 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:
@@ -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.instance
8
- opts.parse([])
19
+ opts = Ditto::Options.new([])
9
20
  opts.connstring.should == Ditto::Options::DEFAULTS[:connstring]
10
- opts.modelpath.should == Ditto::Options::DEFAULTS[:modelpath]
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.loadpaths.size.should == 0
26
+ opts.loadfiles.size.should == 0
15
27
  end
16
28
  it "should return single path" do
17
- opts = Ditto::Options.instance.parse(["testfile"])
29
+ opts = Ditto::Options.new([@file1])
18
30
  opts.connstring.should == Ditto::Options::DEFAULTS[:connstring]
19
- opts.modelpath.should == Ditto::Options::DEFAULTS[:modelpath]
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.loadpaths.should == ["testfile"]
35
+ opts.loadfiles.should == [@file1]
24
36
  end
25
37
  end
26
- context "specifying a model path" do
38
+ context "specifying a dittomart" do
27
39
  it "should return it" do
28
- mpath = "spec"
29
- opts = Ditto::Options.instance.parse(["-m", "#{mpath}", "afile"])
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 model path that doesn't exist" do
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.instance.parse(["-m", "#{mpath}", "afile"])
38
- }.to raise_error(RuntimeError, "Modelpath #{mpath} does not exist!")
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.instance.parse(["-c", "#{mydb}", "afile"])
62
+ opts = Ditto::Options.new(["-c", "#{mydb}"])
45
63
  opts.connstring.should == mydb
46
64
  end
47
65
  end
48
- context "specifying paths and no connection string" do
49
- it "should return the paths" do
50
- opts = Ditto::Options.instance.parse(["file1", "path1"])
51
- opts.loadpaths.should == ["file1", "path1"]
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.instance.parse(["-c", "u/p@//serv:1521/mydb", "file1", "path1"])
57
- opts.loadpaths.should == ["file1", "path1"]
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.instance.parse(["--droptables", "file1", "path1"])
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.instance.parse(["-v", "file1"])
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.instance.parse(["-vv", "file1"])
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
@@ -0,0 +1,7 @@
1
+ # This is a test file
2
+
3
+ currency-1.0.0.dm
4
+
5
+ @nested
6
+
7
+ currency_group-1.0.0.dm