activefacts-generators 1.7.1

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.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +10 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +30 -0
  8. data/Rakefile +6 -0
  9. data/activefacts-generators.gemspec +26 -0
  10. data/lib/activefacts/dependency_analyser.rb +182 -0
  11. data/lib/activefacts/generators/absorption.rb +71 -0
  12. data/lib/activefacts/generators/composition.rb +119 -0
  13. data/lib/activefacts/generators/cql.rb +715 -0
  14. data/lib/activefacts/generators/diagrams/json.rb +340 -0
  15. data/lib/activefacts/generators/help.rb +64 -0
  16. data/lib/activefacts/generators/helpers/inject.rb +16 -0
  17. data/lib/activefacts/generators/helpers/oo.rb +162 -0
  18. data/lib/activefacts/generators/helpers/ordered.rb +605 -0
  19. data/lib/activefacts/generators/helpers/rails.rb +57 -0
  20. data/lib/activefacts/generators/html/glossary.rb +462 -0
  21. data/lib/activefacts/generators/metadata/json.rb +204 -0
  22. data/lib/activefacts/generators/null.rb +32 -0
  23. data/lib/activefacts/generators/rails/models.rb +247 -0
  24. data/lib/activefacts/generators/rails/schema.rb +217 -0
  25. data/lib/activefacts/generators/ruby.rb +134 -0
  26. data/lib/activefacts/generators/sql/mysql.rb +281 -0
  27. data/lib/activefacts/generators/sql/server.rb +274 -0
  28. data/lib/activefacts/generators/stats.rb +70 -0
  29. data/lib/activefacts/generators/text.rb +29 -0
  30. data/lib/activefacts/generators/traits/datavault.rb +241 -0
  31. data/lib/activefacts/generators/traits/oo.rb +73 -0
  32. data/lib/activefacts/generators/traits/ordered.rb +33 -0
  33. data/lib/activefacts/generators/traits/ruby.rb +210 -0
  34. data/lib/activefacts/generators/transform/datavault.rb +303 -0
  35. data/lib/activefacts/generators/transform/surrogate.rb +215 -0
  36. data/lib/activefacts/registry.rb +11 -0
  37. metadata +176 -0
@@ -0,0 +1,215 @@
1
+ #
2
+ # ActiveFacts Schema Transform
3
+ # Transform a loaded ActiveFacts vocabulary to suit ActiveRecord
4
+ #
5
+ # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
6
+ #
7
+ require 'activefacts/metamodel'
8
+ require 'activefacts/rmap'
9
+ require 'activefacts/registry'
10
+
11
+ module ActiveFacts
12
+ module Metamodel
13
+ class ObjectType
14
+
15
+ def add_surrogate type_name = 'Auto Counter', suffix = 'ID'
16
+ # Find or assert the surrogate value type
17
+ auto_counter = vocabulary.valid_value_type_name(type_name) ||
18
+ constellation.ValueType(:vocabulary => vocabulary, :name => type_name, :concept => :new)
19
+
20
+ # Create a subtype to identify this entity type:
21
+ vt_name = self.name + ' '+suffix
22
+ my_id = @vocabulary.valid_value_type_name(vt_name) ||
23
+ constellation.ValueType(:vocabulary => vocabulary, :name => vt_name, :concept => :new, :supertype => auto_counter)
24
+
25
+ # Create a fact type
26
+ identifying_fact_type = constellation.FactType(:concept => :new)
27
+ my_role = constellation.Role(:concept => :new, :fact_type => identifying_fact_type, :ordinal => 0, :object_type => self)
28
+ @injected_surrogate_role = my_role
29
+ id_role = constellation.Role(:concept => :new, :fact_type => identifying_fact_type, :ordinal => 1, :object_type => my_id)
30
+
31
+ # Create a reading (which needs a RoleSequence)
32
+ reading = constellation.Reading(
33
+ :fact_type => identifying_fact_type,
34
+ :ordinal => 0,
35
+ :role_sequence => [:new],
36
+ :text => "{0} has {1}"
37
+ )
38
+ constellation.RoleRef(:role_sequence => reading.role_sequence, :ordinal => 0, :role => my_role)
39
+ constellation.RoleRef(:role_sequence => reading.role_sequence, :ordinal => 1, :role => id_role)
40
+
41
+ # Create two uniqueness constraints for the one-to-one. Each needs a RoleSequence (two RoleRefs)
42
+ one_id = constellation.PresenceConstraint(
43
+ :concept => :new,
44
+ :vocabulary => vocabulary,
45
+ :name => self.name+'HasOne'+suffix,
46
+ :role_sequence => [:new],
47
+ :is_mandatory => true,
48
+ :min_frequency => 1,
49
+ :max_frequency => 1,
50
+ :is_preferred_identifier => false
51
+ )
52
+ @constellation.RoleRef(:role_sequence => one_id.role_sequence, :ordinal => 0, :role => my_role)
53
+
54
+ one_me = constellation.PresenceConstraint(
55
+ :concept => :new,
56
+ :vocabulary => vocabulary,
57
+ :name => self.name+suffix+'IsOfOne'+self.name,
58
+ :role_sequence => [:new],
59
+ :is_mandatory => false,
60
+ :min_frequency => 0,
61
+ :max_frequency => 1,
62
+ :is_preferred_identifier => true
63
+ )
64
+ @constellation.RoleRef(:role_sequence => one_me.role_sequence, :ordinal => 0, :role => id_role)
65
+ end
66
+ end
67
+
68
+ class ValueType
69
+ def needs_surrogate
70
+ !is_auto_assigned
71
+ end
72
+
73
+ def inject_surrogate
74
+ trace :transform_surrogate, "Adding surrogate ID to Value Type #{name}"
75
+ add_surrogate('Auto Counter', 'ID')
76
+ end
77
+ end
78
+
79
+ class EntityType
80
+ def identifying_refs_from
81
+ pi = preferred_identifier
82
+ rrs = pi.role_sequence.all_role_ref
83
+
84
+ # REVISIT: This is actually a ref to us, not from
85
+ # if absorbed_via
86
+ # return [absorbed_via]
87
+ # end
88
+
89
+ rrs.map do |rr|
90
+ r = references_from.detect{|ref| rr.role == ref.to_role }
91
+ raise "failed to find #{name} identifying reference for #{rr.role.object_type.name} in #{references_from.inspect}" unless r
92
+ r
93
+ end
94
+ end
95
+
96
+ def needs_surrogate
97
+
98
+ # A recursive proc to replace any reference to an Entity Type by its identifying references:
99
+ trace :transform_surrogate_expansion, "Expanding key for #{name}"
100
+ substitute_identifying_refs = proc do |object|
101
+ if ref = object.absorbed_via
102
+ # This shouldn't be necessary, but see the absorbed_via comment above.
103
+ absorbed_into = ref.from
104
+ trace :transform_surrogate_expansion, "recursing to handle absorption of #{object.name} into #{absorbed_into.name}"
105
+ [substitute_identifying_refs.call(absorbed_into)]
106
+ else
107
+ irf = object.identifying_refs_from
108
+ trace :transform_surrogate_expansion, "Iterating for #{object.name} over #{irf.inspect}" do
109
+ irf.each_with_index do |ref, i|
110
+ next if ref.is_unary
111
+ next if ref.to_role.object_type.kind_of?(ActiveFacts::Metamodel::ValueType)
112
+ recurse_to = ref.to_role.object_type
113
+
114
+ trace :transform_surrogate_expansion, "#{i}: recursing to expand #{recurse_to.name} key in #{ref}" do
115
+ irf[i] = substitute_identifying_refs.call(recurse_to)
116
+ end
117
+ end
118
+ end
119
+ irf
120
+ end
121
+ end
122
+ irf = substitute_identifying_refs.call(self)
123
+
124
+ trace :transform_surrogate, "Does #{name} need a surrogate? it's identified by #{irf.inspect}" do
125
+
126
+ pk_fks = identifying_refs_from.map do |ref|
127
+ ref.to && ref.to.is_table ? ref.to : nil
128
+ end
129
+
130
+ irf.flatten!
131
+
132
+ # Multi-part identifiers are only allowed if:
133
+ # * each part is a foreign key (i.e. it's a join table),
134
+ # * there are no other columns (that might require updating) and
135
+ # * the object is not the target of a foreign key:
136
+ if irf.size >= 2
137
+ if pk_fks.include?(nil)
138
+ trace :transform_surrogate, "#{self.name} needs a surrogate because its multi-part key contains a non-table"
139
+ return true
140
+ elsif references_to.size != 0
141
+ trace :transform_surrogate, "#{self.name} is a join table between #{pk_fks.map(&:name).inspect} but is also an FK target"
142
+ return true
143
+ elsif (references_from-identifying_refs_from).size > 0
144
+ # There are other attributes to worry about
145
+ return true
146
+ else
147
+ trace :transform_surrogate, "#{self.name} is a join table between #{pk_fks.map(&:name).inspect}"
148
+ return false
149
+ end
150
+ return true
151
+ end
152
+
153
+ # Single-part key. It must be an Auto Counter, or we will add a surrogate
154
+
155
+ identifying_type = irf[0].to
156
+ if identifying_type.needs_surrogate
157
+ trace :transform_surrogate, "#{self.name} needs a surrogate because #{irf[0].to.name} is not an AutoCounter, but #{identifying_type.supertypes_transitive.map(&:name).inspect}"
158
+ return true
159
+ end
160
+
161
+ false
162
+ end
163
+ end
164
+
165
+ def inject_surrogate
166
+ trace :transform_surrogate, "Injecting a surrogate key into #{self.name}"
167
+
168
+ # Disable the preferred identifier:
169
+ pi = preferred_identifier
170
+ trace :transform_surrogate, "pi for #{name} was '#{pi.describe}'"
171
+ pi.is_preferred_identifier = false
172
+ @preferred_identifier = nil # Kill the cache
173
+
174
+ add_surrogate
175
+
176
+ trace :transform_surrogate, "pi for #{name} is now '#{preferred_identifier.describe}'"
177
+ end
178
+
179
+ end
180
+ end
181
+
182
+ module RMap
183
+ class Column
184
+ def is_injected_surrogate
185
+ references.size == 1 and
186
+ references[0].from_role == references[0].from.injected_surrogate_role
187
+ end
188
+ end
189
+ end
190
+
191
+ module Generators #:nodoc:
192
+ module Transform #:nodoc:
193
+ class Surrogate
194
+ def initialize(vocabulary, *options)
195
+ @vocabulary = vocabulary
196
+ end
197
+
198
+ def generate(out = $stdout)
199
+ @out = out
200
+ injections =
201
+ @vocabulary.tables.select do |table|
202
+ table.needs_surrogate
203
+ end
204
+ injections.each do |table|
205
+ table.inject_surrogate
206
+ end
207
+
208
+ @vocabulary.decide_tables
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end
214
+
215
+ ActiveFacts::Registry.generator('transform/surrogate', ActiveFacts::Generators::Transform::Surrogate)
@@ -0,0 +1,11 @@
1
+ module ActiveFacts
2
+ module Registry
3
+ def self.generator(name, klass)
4
+ generators[name] = klass
5
+ end
6
+
7
+ def self.generators
8
+ @@generators ||= {}
9
+ end
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,176 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activefacts-generators
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.7.1
5
+ platform: ruby
6
+ authors:
7
+ - Clifford Heath
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-10-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.10.a
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.10.a
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
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: activefacts-metamodel
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 1.7.0
62
+ - - "~>"
63
+ - !ruby/object:Gem::Version
64
+ version: '1.7'
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: 1.7.0
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.7'
75
+ - !ruby/object:Gem::Dependency
76
+ name: activefacts-rmap
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: 1.7.0
82
+ - - "~>"
83
+ - !ruby/object:Gem::Version
84
+ version: '1.7'
85
+ type: :runtime
86
+ prerelease: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: 1.7.0
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '1.7'
95
+ - !ruby/object:Gem::Dependency
96
+ name: activesupport
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ description: Code generators for the ActiveFacts Fact Modeling suite, including the
110
+ Constellation Query Language
111
+ email:
112
+ - clifford.heath@gmail.com
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - ".gitignore"
118
+ - ".rspec"
119
+ - ".travis.yml"
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - Rakefile
124
+ - activefacts-generators.gemspec
125
+ - lib/activefacts/dependency_analyser.rb
126
+ - lib/activefacts/generators/absorption.rb
127
+ - lib/activefacts/generators/composition.rb
128
+ - lib/activefacts/generators/cql.rb
129
+ - lib/activefacts/generators/diagrams/json.rb
130
+ - lib/activefacts/generators/help.rb
131
+ - lib/activefacts/generators/helpers/inject.rb
132
+ - lib/activefacts/generators/helpers/oo.rb
133
+ - lib/activefacts/generators/helpers/ordered.rb
134
+ - lib/activefacts/generators/helpers/rails.rb
135
+ - lib/activefacts/generators/html/glossary.rb
136
+ - lib/activefacts/generators/metadata/json.rb
137
+ - lib/activefacts/generators/null.rb
138
+ - lib/activefacts/generators/rails/models.rb
139
+ - lib/activefacts/generators/rails/schema.rb
140
+ - lib/activefacts/generators/ruby.rb
141
+ - lib/activefacts/generators/sql/mysql.rb
142
+ - lib/activefacts/generators/sql/server.rb
143
+ - lib/activefacts/generators/stats.rb
144
+ - lib/activefacts/generators/text.rb
145
+ - lib/activefacts/generators/traits/datavault.rb
146
+ - lib/activefacts/generators/traits/oo.rb
147
+ - lib/activefacts/generators/traits/ordered.rb
148
+ - lib/activefacts/generators/traits/ruby.rb
149
+ - lib/activefacts/generators/transform/datavault.rb
150
+ - lib/activefacts/generators/transform/surrogate.rb
151
+ - lib/activefacts/registry.rb
152
+ homepage: http://github.com/cjheath/activefacts-generators
153
+ licenses:
154
+ - MIT
155
+ metadata: {}
156
+ post_install_message:
157
+ rdoc_options: []
158
+ require_paths:
159
+ - lib
160
+ required_ruby_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ required_rubygems_version: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - ">="
168
+ - !ruby/object:Gem::Version
169
+ version: '0'
170
+ requirements: []
171
+ rubyforge_project:
172
+ rubygems_version: 2.2.2
173
+ signing_key:
174
+ specification_version: 4
175
+ summary: Code Generators for the ActiveFacts suite
176
+ test_files: []