activefacts-compositions 1.9.5 → 1.9.6

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.
@@ -0,0 +1,62 @@
1
+ #
2
+ # ActiveFacts Standard SQL Schema Generator
3
+ #
4
+ # Copyright (c) 2009-2016 Clifford Heath. Read the LICENSE file.
5
+ #
6
+ require 'digest/sha1'
7
+ require 'activefacts/metamodel'
8
+ require 'activefacts/registry'
9
+ require 'activefacts/compositions'
10
+ require 'activefacts/generator/sql'
11
+
12
+ module ActiveFacts
13
+ module Generators
14
+ # Options are comma or space separated:
15
+ # * underscore
16
+ class SQL
17
+ class Server < SQL
18
+ def boolean_type
19
+ 'BOOLEAN'
20
+ end
21
+
22
+ def surrogate_type
23
+ 'BIGINT IDENTITY NOT NULL'
24
+ end
25
+
26
+ def reserved_words
27
+ @reserved_words ||= %w{
28
+ ADD ALL ALTER AND ANY AS ASC AUTHORIZATION BACKUP BEGIN
29
+ BETWEEN BREAK BROWSE BULK BY CASCADE CASE CHECK CHECKPOINT
30
+ CLOSE CLUSTERED COALESCE COLLATE COLUMN COMMIT COMPUTE
31
+ CONSTRAINT CONTAINS CONTAINSTABLE CONTINUE CONVERT CREATE
32
+ CROSS CURRENT CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP
33
+ CURRENT_USER CURSOR DATABASE DBCC DEALLOCATE DECLARE
34
+ DEFAULT DELETE DENY DESC DISK DISTINCT DISTRIBUTED DOUBLE
35
+ DROP DUMMY DUMP ELSE END ERRLVL ESCAPE EXCEPT EXEC EXECUTE
36
+ EXISTS EXIT FETCH FILE FILLFACTOR FOR FOREIGN FREETEXT
37
+ FREETEXTTABLE FROM FULL FUNCTION GOTO GRANT GROUP HAVING
38
+ HOLDLOCK IDENTITY IDENTITYCOL IDENTITY_INSERT IF IN INDEX
39
+ INNER INSERT INTERSECT INTO IS JOIN KEY KILL LEFT LIKE
40
+ LINENO LOAD NATIONAL NOCHECK NONCLUSTERED NOT NULL NULLIF
41
+ OF OFF OFFSETS ON OPEN OPENDATASOURCE OPENQUERY OPENROWSET
42
+ OPENXML OPTION OR ORDER OUTER OVER PERCENT PLAN PRECISION
43
+ PRIMARY PRINT PROC PROCEDURE PUBLIC RAISERROR READ READTEXT
44
+ RECONFIGURE REFERENCES REPLICATION RESTORE RESTRICT RETURN
45
+ REVOKE RIGHT ROLLBACK ROWCOUNT ROWGUIDCOL RULE SAVE SCHEMA
46
+ SELECT SESSION_USER SET SETUSER SHUTDOWN SOME STATISTICS
47
+ SYSTEM_USER TABLE TEXTSIZE THEN TO TOP TRAN TRANSACTION
48
+ TRIGGER TRUNCATE TSEQUAL UNION UNIQUE UPDATE UPDATETEXT
49
+ USE USER VALUES VARYING VIEW WAITFOR WHEN WHERE WHILE
50
+ WITH WRITETEXT
51
+ }
52
+ end
53
+
54
+ def go s = ''
55
+ "#{s}\nGO\n" # REVISIT: This is an SQL-Serverism. Move it to a subclass.
56
+ end
57
+ end
58
+
59
+ end
60
+ publish_generator SQL::Server
61
+ end
62
+ end
@@ -0,0 +1,98 @@
1
+ #
2
+ # ActiveFacts Compositions, Metamodel aspect to create a textual summary of a composition and its Composites
3
+ #
4
+ # Copyright (c) 2015 Clifford Heath. Read the LICENSE file.
5
+ #
6
+ require "activefacts/metamodel"
7
+ require "activefacts/compositions/names"
8
+ require "activefacts/compositions/constraints"
9
+ require "activefacts/generator"
10
+
11
+ module ActiveFacts
12
+ module Metamodel
13
+ class Composition
14
+ def summary
15
+ classify_constraints
16
+ "Summary of #{name}\n" +
17
+ all_composite.
18
+ sort_by{|composite| composite.mapping.name}.
19
+ flat_map do |composite|
20
+ composite.summary
21
+ end*''
22
+ end
23
+ end
24
+
25
+ class Composite
26
+ def summary
27
+ indices = self.all_indices_by_rank
28
+
29
+ (
30
+ [mapping.name+"\n"] +
31
+ mapping.
32
+ leaves.
33
+ reject{|leaf| leaf.is_a?(Absorption) && leaf.forward_absorption}.
34
+ flat_map do |leaf|
35
+
36
+ # Build a display of the names in this absorption path, with FK and optional indicators
37
+ path_names = leaf.path.map do |component|
38
+ is_mandatory = case component
39
+ when Indicator
40
+ false
41
+ when Absorption
42
+ component.parent_role.is_mandatory
43
+ else
44
+ true
45
+ end
46
+
47
+ if component.is_a?(Absorption) && component.foreign_key
48
+ "[#{component.name}]"
49
+ else
50
+ component.name
51
+ end +
52
+ (is_mandatory ? '' : '?')
53
+ end*'->'
54
+
55
+ # Build a symbolic representation of the index participation of this leaf
56
+ pos = 0
57
+ indexing = indices.inject([]) do |a, index|
58
+ pos += 1
59
+ if part = index.position_in_index(leaf)
60
+ a << "#{pos}.#{part}"
61
+ end
62
+ a
63
+ end
64
+ if indexing.empty?
65
+ indexing = ''
66
+ else
67
+ indexing = "[#{indexing*','}]"
68
+ end
69
+
70
+ column_name = leaf.column_name.capwords*' '
71
+ ["\t#{path_names}#{indexing} as #{column_name.inspect}\n"] +
72
+ leaf.all_leaf_constraint.map{|leaf_constraint| "\t\t### #{leaf_constraint.leaf_constraint.describe}\n"}
73
+ end +
74
+ all_local_constraint.map do |local_constraint|
75
+ "\t### #{local_constraint.local_constraint.describe}\n"
76
+ end.sort +
77
+ all_spanning_constraint.map do |spanning_constraint|
78
+ "### #{spanning_constraint.spanning_constraint.describe}\n"
79
+ end.sort
80
+
81
+ )*''
82
+ end
83
+ end
84
+ end
85
+
86
+ module Generators
87
+ class Summary
88
+ def initialize composition
89
+ @composition = composition
90
+ end
91
+
92
+ def generate
93
+ @composition.summary
94
+ end
95
+ end
96
+ publish_generator Summary
97
+ end
98
+ end
@@ -1,138 +1,158 @@
1
1
  #
2
- # ActiveFacts Compositions validator.
2
+ # ActiveFacts Compositions, Metamodel aspect to look for validation errors in a composition
3
3
  #
4
4
  # Quite a few constraints are not enforced during the construction of a composition.
5
5
  # This method does a post-validation to ensure that everything looks ok.
6
6
  #
7
7
  # Copyright (c) 2015 Clifford Heath. Read the LICENSE file.
8
8
  #
9
+ require "activefacts/metamodel"
9
10
  require "activefacts/compositions/compositor"
11
+ require "activefacts/generator"
10
12
 
11
13
  module ActiveFacts
12
- module Compositions
13
- class Compositor
14
+ module Generators
15
+ class Validate
16
+ def initialize composition, options = {}
17
+ @composition = composition
18
+ @options = options
19
+ end
20
+
21
+ def generate &b
22
+ @composition.validate &b
23
+ nil
24
+ end
25
+ end
26
+ publish_generator Validate
27
+ end
28
+
29
+ module Metamodel
30
+ class Composition
14
31
  def validate &report
32
+ trace.enable 'composition_validator'
15
33
  report ||= proc do |component, problem|
16
- raise "Problem with #{component.inspect}: #{problem}"
34
+ trace :composition_validator, "!!PROBLEM!! #{component.inspect}: #{problem}"
17
35
  end
18
36
 
19
- @composition.all_composite.each do |composite|
20
- validate_composite composite, &report
37
+ all_composite.each do |composite|
38
+ composite.validate &report
21
39
  end
22
40
  end
41
+ end
23
42
 
24
- private
25
- MM = ActiveFacts::Metamodel
26
-
27
- def validate_composite composite, &report
28
- trace :composition_validator?, "Validating #{composite.inspect}" do
29
- report.call(composite, "Has no Mapping") unless composite.mapping
30
- report.call(composite, "Mapping is not a mapping") unless composite.mapping.class == MM::Mapping
31
- report.call(composite.mapping, "Has no ObjectType") unless composite.mapping.object_type
32
- report.call(composite.mapping, "Has no Name") unless composite.mapping.name
33
- report.call(composite.mapping, "Should not have an Ordinal rank") if composite.mapping.ordinal
34
- report.call(composite.mapping, "Should not have a parent mapping") if composite.mapping.parent
35
- report.call(composite.mapping, "Should be the root of its mapping") if composite.mapping.root != composite
36
-
37
- validate_members composite.mapping, &report
38
- validate_access_paths composite, &report
43
+ class Composite
44
+ def validate &report
45
+ trace :composition_validator?, "Validating #{inspect}" do
46
+ report.call(self, "Has no Mapping") unless mapping
47
+ report.call(self, "Mapping is not a mapping") unless mapping.class == Mapping
48
+ report.call(mapping, "Has no ObjectType") unless mapping.object_type
49
+ report.call(mapping, "Has no Name") unless mapping.name
50
+ report.call(mapping, "Should not have an Ordinal rank") if mapping.ordinal
51
+ report.call(mapping, "Should not have a parent mapping") if mapping.parent
52
+ report.call(mapping, "Should be the root of its mapping") if mapping.root != self
53
+
54
+ mapping.validate_members &report
55
+ validate_access_paths &report
56
+ end
57
+ end
58
+
59
+ def validate_access_paths &report
60
+ all_access_path.each do |access_path|
61
+ report.call(access_path, "Must contain at least one IndexField") unless access_path.all_index_field.size > 0
62
+ access_path.all_index_field.each do |index_field|
63
+ report.call(access_path, "#{index_field.inspect} must be an Indicator or played by a ValueType") unless index_field.component.is_a?(Indicator) || index_field.component.object_type.is_a?(ValueType)
64
+ report.call(access_path, "#{index_field.inspect} must be within its composite") unless index_field.component.root == self
65
+ end
66
+ if ForeignKey === access_path
67
+ if access_path.all_index_field.size == access_path.all_foreign_key_field.size
68
+ access_path.all_index_field.to_a.zip(access_path.all_foreign_key_field.to_a).each do |index_field, foreign_key_field|
69
+ report.call(access_path, "#{index_field.inspect} must have matching target type") unless index_field.component.class == foreign_key_field.component.class
70
+ unless index_field.component.class == foreign_key_field.component.class
71
+ report.call(access_path, "#{index_field.inspect} must have component type matching #{foreign_key_field.inspect}")
72
+ else
73
+ report.call(access_path, "#{index_field.inspect} must have matching target type") unless !index_field.component.is_a?(Absorption) or index_field.component.object_type == foreign_key_field.component.object_type
74
+ end
75
+ report.call(access_path, "#{foreign_key_field.inspect} must be within the target composite") unless foreign_key_field.component.root == access_path.source_composite
76
+ end
77
+ else
78
+ report.call(access_path, "has #{access_path.all_index_field.size} index fields but #{access_path.all_foreign_key_field.size} ForeignKeyField")
79
+ end
80
+ end
39
81
  end
40
82
  end
83
+ end
41
84
 
42
- def validate_members mapping, &report
85
+ class Mapping
86
+ def validate_members &report
43
87
  # Names (except of subtype/supertype absorption) must be unique:
44
- names = mapping.
45
- all_member.
46
- reject{|m| m.is_a?(MM::Absorption) && m.parent_role.fact_type.is_a?(MM::TypeInheritance)}.
88
+ names = all_member.
89
+ reject{|m| m.is_a?(Absorption) && m.parent_role.fact_type.is_a?(TypeInheritance)}.
47
90
  map(&:name).
48
91
  compact
49
92
  duplicate_names = names.select{|name| names.count(name) > 1}.uniq
50
- report.call(mapping, "Contains duplicated names #{duplicate_names.map(&:inspect)*', '}") unless duplicate_names.empty?
93
+ report.call(self, "Contains duplicated names #{duplicate_names.map(&:inspect)*', '}") unless duplicate_names.empty?
51
94
 
52
- mapping.all_member.each do |member|
95
+ all_member.each do |member|
53
96
  trace :composition_validator?, "Validating #{member.inspect}" do
54
- report.call(member, "Requires a name") unless MM::Absorption === member && member.flattens or member.name && !member.name.empty?
97
+ report.call(member, "Requires a name") unless Absorption === member && member.flattens or member.name && !member.name.empty?
55
98
  case member
56
- when MM::Absorption
99
+ when Absorption
57
100
  p = member.parent_role
58
101
  c = member.child_role
59
102
  report.call(member, "Roles should belong to the same fact type, but instead we have #{p.name} in #{p.fact_type.default_reading} and #{c.name} in #{c.fact_type.default_reading}") unless p.fact_type == c.fact_type
60
103
  report.call(member, "Object type #{member.object_type.name} should play the child role #{c.name}") unless member.object_type == c.object_type
61
- report.call(member, "Parent mapping object type #{mapping.object_type.name} should play the parent role #{p.name}") unless mapping.object_type == p.object_type
62
-
63
- validate_reverse member, &report
64
- validate_nesting member, &report if member.all_nesting.size > 0
104
+ report.call(member, "Parent mapping object type #{object_type.name} should play the parent role #{p.name}") unless object_type == p.object_type
65
105
 
66
- validate_members member, &report
106
+ member.validate_reverse &report
107
+ member.validate_nesting &report if member.all_nesting.size > 0
108
+ member.validate_members &report
67
109
 
68
- when MM::Scoping
110
+ when Scoping
69
111
  report.call(member, "REVISIT: Unexpected and unchecked Scoping")
70
112
 
71
- when MM::ValueField
113
+ when ValueField
72
114
  # Nothing to check here
73
115
 
74
- when MM::SurrogateKey
116
+ when SurrogateKey
75
117
  # Nothing to check here
76
118
 
77
- when MM::Injection
119
+ when Injection
78
120
  report.call(member, "REVISIT: Unexpected and unchecked Injection")
79
121
 
80
- when MM::Mapping
122
+ when Mapping
81
123
  report.call(member, "A child Component should not be a bare Mapping")
82
124
 
83
- when MM::Indicator
125
+ when Indicator
84
126
  report.call(member, "Indicator requires a Role") unless member.role
85
127
 
86
- when MM::Discriminator
128
+ when Discriminator
87
129
  report.call(member, "Discriminator requires at least one Discriminated Role") if member.all_discriminated_role.empty?
88
130
  member.all_discriminated_role.each do |role|
89
- report.call(member, "Discriminated Role #{role.name} is not played by parent object type #{mapping.object_type.name}") unless role.object_type == mapping.object_type
131
+ report.call(member, "Discriminated Role #{role.name} is not played by parent object type #{object_type.name}") unless role.object_type == object_type
90
132
  end
91
133
  # REVISIT: Discriminated Roles must have distinct values matching the type of the Role
92
134
  end
93
135
  end
94
136
  end
95
137
  end
138
+ end
96
139
 
97
- def validate_reverse absorption, &report
98
- reverse = absorption.forward_absorption || absorption.reverse_absorption
140
+ class Absorption
141
+ def validate_reverse &report
142
+ reverse = forward_absorption || reverse_absorption
99
143
  return unless reverse
100
- report.call(absorption, "Opposite absorption's child role #{reverse.child_role.name} should match parent role #{absorption.parent_role.name}") unless reverse.child_role == absorption.parent_role
101
- report.call(absorption, "Opposite absorption's parent role #{reverse.parent_role.name} should match child role #{absorption.child_role.name}") unless reverse.parent_role == absorption.child_role
144
+ report.call(self, "Opposite absorption's child role #{reverse.child_role.name} should match parent role #{parent_role.name}") unless reverse.child_role == parent_role
145
+ report.call(self, "Opposite absorption's parent role #{reverse.parent_role.name} should match child role #{child_role.name}") unless reverse.parent_role == child_role
102
146
  end
103
147
 
104
- def validate_nesting absorption, &report
105
- report.call(absorption, "REVISIT: Unexpected and unchecked Nesting")
106
- report.call(absorption, "Nesting Mode must be specified") unless absorption.nesting_mode
148
+ def validate_nesting &report
149
+ report.call(self, "REVISIT: Unexpected and unchecked Nesting")
150
+ report.call(self, "Nesting Mode must be specified") unless self.nesting_mode
107
151
  # REVISIT: Nesting names must be unique
108
152
  # REVISIT: Nesting roles must be played by...
109
153
  # REVISIT: Nesting roles must be value types
110
154
  end
111
-
112
- def validate_access_paths composite, &report
113
- composite.all_access_path.each do |access_path|
114
- report.call(access_path, "Must contain at least one IndexField") unless access_path.all_index_field.size > 0
115
- access_path.all_index_field.each do |index_field|
116
- report.call(access_path, "#{index_field.inspect} must be an Indicator or played by a ValueType") unless index_field.component.is_a?(MM::Indicator) || index_field.component.object_type.is_a?(MM::ValueType)
117
- report.call(access_path, "#{index_field.inspect} must be within its composite") unless index_field.component.root == composite
118
- end
119
- if MM::ForeignKey === access_path
120
- if access_path.all_index_field.size == access_path.all_foreign_key_field.size
121
- access_path.all_index_field.to_a.zip(access_path.all_foreign_key_field.to_a).each do |index_field, foreign_key_field|
122
- report.call(access_path, "#{index_field.inspect} must have matching target type") unless index_field.component.class == foreign_key_field.component.class
123
- unless index_field.component.class == foreign_key_field.component.class
124
- report.call(access_path, "#{index_field.inspect} must have component type matching #{foreign_key_field.inspect}")
125
- else
126
- report.call(access_path, "#{index_field.inspect} must have matching target type") unless !index_field.component.is_a?(MM::Absorption) or index_field.component.object_type == foreign_key_field.component.object_type
127
- end
128
- report.call(access_path, "#{foreign_key_field.inspect} must be within the target composite") unless foreign_key_field.component.root == access_path.source_composite
129
- end
130
- else
131
- report.call(access_path, "has #{access_path.all_index_field.size} index fields but #{access_path.all_foreign_key_field.size} ForeignKeyField")
132
- end
133
- end
134
- end
135
- end
136
155
  end
156
+
137
157
  end
138
158
  end
@@ -0,0 +1,28 @@
1
+ #
2
+ # Enumerate files with "extension" in directories called "path" anywhere in the Ruby LOAD_PATH
3
+ #
4
+ class Loadable
5
+ def initialize path = "", extension = '.rb'
6
+ @path = path
7
+ @extension = extension
8
+ end
9
+
10
+ def enumerate
11
+ $LOAD_PATH.
12
+ flat_map do |dir|
13
+ dir_path = (dir+"/"+@path).gsub(%r{//+}, '/')
14
+ pattern = dir_path+"/**/*"+@extension
15
+ Dir[pattern].
16
+ map do |p|
17
+ p.
18
+ sub(%r{#{Regexp.escape(dir_path)}/}, '').
19
+ sub(%r{#{@extension}}, '')
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+
26
+ if __FILE__ == $0
27
+ p Loadable.new(*ARGV).enumerate
28
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activefacts-compositions
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.5
4
+ version: 1.9.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clifford Heath
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-29 00:00:00.000000000 Z
11
+ date: 2016-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -59,7 +59,7 @@ dependencies:
59
59
  - !ruby/object:Gem::Version
60
60
  version: '3.3'
61
61
  - !ruby/object:Gem::Dependency
62
- name: activefacts-api
62
+ name: activefacts
63
63
  requirement: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - "~>"
@@ -67,8 +67,8 @@ dependencies:
67
67
  version: '1'
68
68
  - - ">="
69
69
  - !ruby/object:Gem::Version
70
- version: 1.9.4
71
- type: :runtime
70
+ version: '1.8'
71
+ type: :development
72
72
  prerelease: false
73
73
  version_requirements: !ruby/object:Gem::Requirement
74
74
  requirements:
@@ -77,9 +77,9 @@ dependencies:
77
77
  version: '1'
78
78
  - - ">="
79
79
  - !ruby/object:Gem::Version
80
- version: 1.9.4
80
+ version: '1.8'
81
81
  - !ruby/object:Gem::Dependency
82
- name: activefacts-metamodel
82
+ name: activefacts-api
83
83
  requirement: !ruby/object:Gem::Requirement
84
84
  requirements:
85
85
  - - "~>"
@@ -99,45 +99,45 @@ dependencies:
99
99
  - !ruby/object:Gem::Version
100
100
  version: 1.9.5
101
101
  - !ruby/object:Gem::Dependency
102
- name: tracing
102
+ name: activefacts-metamodel
103
103
  requirement: !ruby/object:Gem::Requirement
104
104
  requirements:
105
105
  - - "~>"
106
106
  - !ruby/object:Gem::Version
107
- version: '2'
107
+ version: '1'
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
- version: 2.0.6
110
+ version: 1.9.6
111
111
  type: :runtime
112
112
  prerelease: false
113
113
  version_requirements: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '2'
117
+ version: '1'
118
118
  - - ">="
119
119
  - !ruby/object:Gem::Version
120
- version: 2.0.6
120
+ version: 1.9.6
121
121
  - !ruby/object:Gem::Dependency
122
- name: activefacts
122
+ name: tracing
123
123
  requirement: !ruby/object:Gem::Requirement
124
124
  requirements:
125
125
  - - "~>"
126
126
  - !ruby/object:Gem::Version
127
- version: '1'
127
+ version: '2'
128
128
  - - ">="
129
129
  - !ruby/object:Gem::Version
130
- version: '1.8'
131
- type: :development
130
+ version: 2.0.6
131
+ type: :runtime
132
132
  prerelease: false
133
133
  version_requirements: !ruby/object:Gem::Requirement
134
134
  requirements:
135
135
  - - "~>"
136
136
  - !ruby/object:Gem::Version
137
- version: '1'
137
+ version: '2'
138
138
  - - ">="
139
139
  - !ruby/object:Gem::Version
140
- version: '1.8'
140
+ version: 2.0.6
141
141
  - !ruby/object:Gem::Dependency
142
142
  name: activefacts-cql
143
143
  requirement: !ruby/object:Gem::Requirement
@@ -148,7 +148,7 @@ dependencies:
148
148
  - - ">="
149
149
  - !ruby/object:Gem::Version
150
150
  version: '1.8'
151
- type: :development
151
+ type: :runtime
152
152
  prerelease: false
153
153
  version_requirements: !ruby/object:Gem::Requirement
154
154
  requirements:
@@ -162,7 +162,8 @@ description: Create and represent composite schemas, schema transforms and data
162
162
  over a fact-based model
163
163
  email:
164
164
  - clifford.heath@gmail.com
165
- executables: []
165
+ executables:
166
+ - schema_compositor
166
167
  extensions: []
167
168
  extra_rdoc_files: []
168
169
  files:
@@ -178,9 +179,18 @@ files:
178
179
  - lib/activefacts/compositions.rb
179
180
  - lib/activefacts/compositions/binary.rb
180
181
  - lib/activefacts/compositions/compositor.rb
182
+ - lib/activefacts/compositions/constraints.rb
183
+ - lib/activefacts/compositions/names.rb
181
184
  - lib/activefacts/compositions/relational.rb
182
- - lib/activefacts/compositions/validator.rb
183
185
  - lib/activefacts/compositions/version.rb
186
+ - lib/activefacts/generator.rb
187
+ - lib/activefacts/generator/oo.rb
188
+ - lib/activefacts/generator/ruby.rb
189
+ - lib/activefacts/generator/sql.rb
190
+ - lib/activefacts/generator/sql/server.rb
191
+ - lib/activefacts/generator/summary.rb
192
+ - lib/activefacts/generator/validate.rb
193
+ - lib/activefacts/loadable.rb
184
194
  homepage: https://github.com/cjheath/activefacts-compositions
185
195
  licenses:
186
196
  - MIT