activefacts-generators 1.8.2 → 1.8.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fae26b2c7cc83608173f074aaed203e14715b5a5
4
- data.tar.gz: c4d0e31dc92866f042a82baebe67c0369414cb2d
3
+ metadata.gz: 18414a4533151ffe192e7ae375366327595faf25
4
+ data.tar.gz: 6d31af89a93cfa0d63edf126cacb3df917770cd3
5
5
  SHA512:
6
- metadata.gz: d2f8719f99dcb8f5b4425d46e558e9862ba0a0dc51c16ab58a67c78ba4faa0add7fc2ced31fc5a58188bc568a7b76fdfecb23892fda04261591a8c8806bc68f4
7
- data.tar.gz: 930d7bc060c4d53c4913dec4510b4609dd1177cc13a005e1e13993527ee083a79e32e3f600b60b25c8381c17df72f3d016d713aacc732b40a57163151d9cd406
6
+ metadata.gz: 314a64ec5dcf991328ef3ffcc1fdb18b5f99673bb1c27695d0e9f796ac922c26b0acb94517c146401dbb08d3e6adbc965c6e44b43ce13e22d0bbf8cf021a2b50
7
+ data.tar.gz: 0ed72bc6312ef1eae1059d5a93f530b056f9cec1ea7b690eaa93f1e6933be4dc4376cf2175f82846e8cf6dd49972714402ce3c539d76a1b828baffd915335905
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "activefacts-generators"
7
- spec.version = "1.8.2"
7
+ spec.version = "1.8.3"
8
8
  spec.authors = ["Clifford Heath"]
9
9
  spec.email = ["clifford.heath@gmail.com"]
10
10
 
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
17
  spec.require_paths = ["lib"]
18
18
 
19
- spec.add_development_dependency "bundler", ">= 1.10", "~> 1.10.6"
19
+ spec.add_development_dependency "bundler", ">= 1.10"
20
20
  spec.add_development_dependency "rake", "~> 10.0"
21
21
  spec.add_development_dependency "rspec", "~> 3.3"
22
22
 
@@ -2,29 +2,29 @@ module ActiveFacts
2
2
  module Generators
3
3
  module Rails
4
4
  module Helpers
5
- def rails_plural_name name
6
- # Crunch spaces and pluralise the first part, all in snake_case
7
- name.pop if name.is_a?(Array) and name.last == []
8
- name = name[0]*'_' if name.is_a?(Array) and name.size == 1
9
- if name.is_a?(Array)
10
- name = ActiveSupport::Inflector.tableize((name[0]*'_').gsub(/\s+/, '_')) +
11
- '_' +
12
- ActiveSupport::Inflector.underscore((name[1..-1].flatten*'_').gsub(/\s+/, '_'))
13
- else
14
- ActiveSupport::Inflector.tableize(name.gsub(/\s+/, '_'))
15
- end
16
- end
17
-
18
- def rails_singular_name name
19
- # Crunch spaces and convert to snake_case
20
- name = name.flatten*'_' if name.is_a?(Array)
21
- ActiveSupport::Inflector.underscore(name.gsub(/\s+/, '_'))
22
- end
23
-
24
- def rails_class_name name
25
- name = name*'_' if name.is_a?(Array)
26
- ActiveSupport::Inflector.camelize(name.gsub(/\s+/, '_'))
27
- end
5
+ def rails_plural_name name
6
+ # Crunch spaces and pluralise the first part, all in snake_case
7
+ name.pop if name.is_a?(Array) and name.last == []
8
+ name = name[0]*'_' if name.is_a?(Array) and name.size == 1
9
+ if name.is_a?(Array)
10
+ name = ActiveSupport::Inflector.tableize((name[0]*'_').gsub(/\s+/, '_')) +
11
+ '_' +
12
+ ActiveSupport::Inflector.underscore((name[1..-1].flatten*'_').gsub(/\s+/, '_'))
13
+ else
14
+ ActiveSupport::Inflector.tableize(name.gsub(/\s+/, '_'))
15
+ end
16
+ end
17
+
18
+ def rails_singular_name name
19
+ # Crunch spaces and convert to snake_case
20
+ name = name.flatten*'_' if name.is_a?(Array)
21
+ ActiveSupport::Inflector.underscore(name.gsub(/\s+/, '_'))
22
+ end
23
+
24
+ def rails_class_name name
25
+ name = name*'_' if name.is_a?(Array)
26
+ ActiveSupport::Inflector.camelize(name.gsub(/\s+/, '_'))
27
+ end
28
28
 
29
29
  end
30
30
  end
@@ -40,16 +40,16 @@ module ActiveFacts
40
40
  include Generate::Rails::Helpers
41
41
 
42
42
  def rails_from_association_name
43
- rails_singular_name(to_name.join('_'))
43
+ rails_singular_name(to_name.join('_'))
44
44
  end
45
45
 
46
46
  def rails_to_association
47
- jump = jump_reference
48
- if jump.is_one_to_one
49
- [ "has_one", rails_singular_name(from_name)]
50
- else
51
- [ "has_many", rails_plural_name(from_name)]
52
- end
47
+ jump = jump_reference
48
+ if jump.is_one_to_one
49
+ [ "has_one", rails_singular_name(from_name)]
50
+ else
51
+ [ "has_many", rails_plural_name(from_name)]
52
+ end
53
53
  end
54
54
 
55
55
  end
@@ -19,212 +19,212 @@ module ActiveFacts
19
19
  module Rails
20
20
  # Generate Rails models for the vocabulary
21
21
  # Invoke as
22
- # afgen --rails/schema[=options] <file>.cql
22
+ # afgen --rails/models[=options] <file>.cql
23
23
  class Models
24
24
 
25
- HEADER = "# Auto-generated from CQL, edits will be lost"
25
+ HEADER = "# Auto-generated from CQL, edits will be lost"
26
26
 
27
27
  private
28
28
 
29
- def initialize(vocabulary, *options)
30
- @vocabulary = vocabulary
31
- @vocabulary = @vocabulary.Vocabulary.values[0] if ActiveFacts::API::Constellation === @vocabulary
32
- help if options.include? "help"
33
- options.delete_if { |option| @output = $1 if option =~ /^output=(.*)/ }
34
- @concern = nil
35
- options.delete_if { |option| @concern = $1 if option =~ /^concern=(.*)/ }
36
- @validations = true
37
- options.delete_if { |option| @validations = eval($1) if option =~ /^validation=(.*)/ }
38
- end
39
-
40
- def help
41
- @helping = true
42
- warn %Q{Options for --rails/schema:
43
- output=dir Overwrite model files into this output directory
44
- concern=name Namespace for the concerns
45
- validation=false Disable generation of validations
29
+ def initialize(vocabulary, *options)
30
+ @vocabulary = vocabulary
31
+ @vocabulary = @vocabulary.Vocabulary.values[0] if ActiveFacts::API::Constellation === @vocabulary
32
+ help if options.include? "help"
33
+ options.delete_if { |option| @output = $1 if option =~ /^output=(.*)/ }
34
+ @concern = nil
35
+ options.delete_if { |option| @concern = $1 if option =~ /^concern=(.*)/ }
36
+ @validations = true
37
+ options.delete_if { |option| @validations = eval($1) if option =~ /^validation=(.*)/ }
38
+ end
39
+
40
+ def help
41
+ @helping = true
42
+ warn %Q{Options for --rails/schema:
43
+ output=dir Overwrite model files into this output directory
44
+ concern=name Namespace for the concerns
45
+ validation=false Disable generation of validations
46
46
  }
47
- end
47
+ end
48
48
 
49
- def warn *a
50
- $stderr.puts *a
51
- end
49
+ def warn *a
50
+ $stderr.puts *a
51
+ end
52
52
 
53
- def puts s
54
- @out.puts s
55
- end
53
+ def puts s
54
+ @out.puts s
55
+ end
56
56
 
57
57
  public
58
- def generate(out = $>) #:nodoc:
59
- return if @helping
60
- @out = out
61
- list_extant_files if @output
62
-
63
- # Populate all foreignkeys first:
64
- @vocabulary.tables.each { |table| table.foreign_keys }
65
- ok = true
66
- @vocabulary.tables.each do |table|
67
- ok &= generate_table(table)
68
- end
69
- $stderr.puts "\# #{@vocabulary.name} generated with errors" unless ok
70
- delete_old_generated_files if @output
71
- ok
72
- end
73
-
74
- def list_extant_files
75
- @preexisting_files = Dir[@output+'/*.rb']
76
- end
77
-
78
- def delete_old_generated_files
79
- remaining = []
80
- cleaned = 0
81
- @preexisting_files.each do |pathname|
82
- if generated_file_exists(pathname) == true
83
- File.unlink(pathname)
84
- cleaned += 1
85
- else
86
- remaining << pathname
87
- end
88
- end
89
- $stderr.puts "Cleaned up #{cleaned} old generated files" if @preexisting_files.size > 0
90
- $stderr.puts "Remaining non-generated files:\n\t#{remaining*"\n\t"}" if remaining.size > 0
91
- end
92
-
93
- def generated_file_exists pathname
94
- File.open(pathname, 'r') do |existing|
95
- first_lines = existing.read(1024) # Make it possible to pass over a magic charset comment
96
- if first_lines.length == 0 or first_lines =~ %r{^#{HEADER}}
97
- return true
98
- end
99
- end
100
- return false # File exists, but is not generated
101
- rescue Errno::ENOENT
102
- return nil # File does not exist
103
- end
104
-
105
- def create_if_ok filename
106
- # Create a file in the output directory, being careful not to overwrite carelessly
107
- if @output
108
- pathname = (@output+'/'+filename).gsub(%r{//+}, '/')
109
- @preexisting_files.reject!{|f| f == pathname } # Don't clean up this file
110
- if generated_file_exists(pathname) == false
111
- $stderr.puts "not overwriting non-generated file #{pathname}"
112
- @individual_file = nil
113
- return
114
- end
115
- @individual_file = @out = File.open(pathname, 'w')
116
- puts "#{HEADER}"
117
- end
118
- true
119
- end
120
-
121
- def to_associations table
122
- # belongs_to Associations
123
- table.foreign_keys.map do |fk|
124
- association_name = fk.rails_from_association_name
125
-
126
- if association_name != fk.to.rails_singular_name
127
- # A different class_name is implied, emit an explicit one:
128
- class_name = ", :class_name => '#{fk.to.rails_class_name}'"
129
- end
130
- foreign_key = ", :foreign_key => :#{fk.from_columns[0].rails_name}"
131
- if foreign_key == fk.to.rails_singular_name+'_id'
132
- # See lib/active_record/reflection.rb, method #derive_foreign_key
133
- foreign_key = ''
134
- end
135
-
136
- %Q{
58
+ def generate(out = $>) #:nodoc:
59
+ return if @helping
60
+ @out = out
61
+ list_extant_files if @output
62
+
63
+ # Populate all foreignkeys first:
64
+ @vocabulary.tables.each { |table| table.foreign_keys }
65
+ ok = true
66
+ @vocabulary.tables.each do |table|
67
+ ok &= generate_table(table)
68
+ end
69
+ warn "\# #{@vocabulary.name} generated with errors" unless ok
70
+ delete_old_generated_files if @output
71
+ ok
72
+ end
73
+
74
+ def list_extant_files
75
+ @preexisting_files = Dir[@output+'/*.rb']
76
+ end
77
+
78
+ def delete_old_generated_files
79
+ remaining = []
80
+ cleaned = 0
81
+ @preexisting_files.each do |pathname|
82
+ if generated_file_exists(pathname) == true
83
+ File.unlink(pathname)
84
+ cleaned += 1
85
+ else
86
+ remaining << pathname
87
+ end
88
+ end
89
+ $stderr.puts "Cleaned up #{cleaned} old generated files" if @preexisting_files.size > 0
90
+ $stderr.puts "Remaining non-generated files:\n\t#{remaining*"\n\t"}" if remaining.size > 0
91
+ end
92
+
93
+ def generated_file_exists pathname
94
+ File.open(pathname, 'r') do |existing|
95
+ first_lines = existing.read(1024) # Make it possible to pass over a magic charset comment
96
+ if first_lines.length == 0 or first_lines =~ %r{^#{HEADER}}
97
+ return true
98
+ end
99
+ end
100
+ return false # File exists, but is not generated
101
+ rescue Errno::ENOENT
102
+ return nil # File does not exist
103
+ end
104
+
105
+ def create_if_ok filename
106
+ # Create a file in the output directory, being careful not to overwrite carelessly
107
+ if @output
108
+ pathname = (@output+'/'+filename).gsub(%r{//+}, '/')
109
+ @preexisting_files.reject!{|f| f == pathname } # Don't clean up this file
110
+ if generated_file_exists(pathname) == false
111
+ $stderr.puts "not overwriting non-generated file #{pathname}"
112
+ @individual_file = nil
113
+ return
114
+ end
115
+ @individual_file = @out = File.open(pathname, 'w')
116
+ puts "#{HEADER}"
117
+ end
118
+ true
119
+ end
120
+
121
+ def to_associations table
122
+ # belongs_to Associations
123
+ table.foreign_keys.map do |fk|
124
+ association_name = fk.rails_from_association_name
125
+
126
+ if association_name != fk.to.rails_singular_name
127
+ # A different class_name is implied, emit an explicit one:
128
+ class_name = ", :class_name => '#{fk.to.rails_class_name}'"
129
+ end
130
+ foreign_key = ", :foreign_key => :#{fk.from_columns[0].rails_name}"
131
+ if foreign_key == fk.to.rails_singular_name+'_id'
132
+ # See lib/active_record/reflection.rb, method #derive_foreign_key
133
+ foreign_key = ''
134
+ end
135
+
136
+ %Q{
137
137
  \# #{fk.verbalised_path}
138
138
  belongs_to :#{association_name}#{class_name}#{foreign_key}}
139
- end
140
- end
141
-
142
- def from_associations table
143
- # has_one/has_many Associations
144
- table.foreign_keys_to.sort_by{|fk| fk.describe}.map do |fk|
145
- # Get the jump reference
146
-
147
- if fk.from_columns.size > 1
148
- raise "Can't emit Rails associations for multi-part foreign key with #{fk.references.inspect}. Did you mean to use --transform/surrogate"
149
- end
150
-
151
- association_type, association_name = *fk.rails_to_association
152
-
153
- ref = fk.jump_reference
154
- [
155
- "\n \# #{fk.verbalised_path(true)}" +
156
- "\n" +
157
- %Q{ #{association_type} :#{association_name}} +
158
- %Q{, :class_name => '#{fk.from.rails_class_name}'} +
159
- %Q{, :foreign_key => :#{fk.from_columns[0].rails_name}} +
160
- %Q{, :dependent => :destroy}
161
- ] +
162
- # If ref.from is a join table, we can emit a has_many :through for each other key
163
- # REVISIT Could alternately do this for all belongs_to's in ref.from
164
- if ref.from.identifier_columns.length > 1
165
- ref.from.identifier_columns.map do |ic|
166
- next nil if ic.references[0] == ref or # Skip the back-reference
167
- ic.references[0].is_unary # or use rails_plural_name(ic.references[0].to_names) ?
168
- # This far association name needs to be augmented for its role name
169
- far_association_name = ic.references[0].to.rails_name
170
- %Q{ has_many :#{far_association_name}, :through => :#{association_name}} # \# via #{ic.name}}
171
- end
172
- else
173
- []
174
- end
175
- end.flatten.compact
176
- end
177
-
178
- def column_constraints table
179
- return [] unless @validations
180
- ccs =
181
- table.columns.map do |column|
182
- name = column.rails_name
183
- column.is_mandatory &&
184
- !column.is_auto_assigned && !column.is_auto_timestamp ? [
185
- " validates :#{name}, :presence => true"
186
- ] : []
187
- end.flatten
188
- ccs.unshift("") unless ccs.empty?
189
- ccs
190
- end
191
-
192
- def model_body table
193
- %Q{module #{table.rails_class_name}
139
+ end
140
+ end
141
+
142
+ def from_associations table
143
+ # has_one/has_many Associations
144
+ table.foreign_keys_to.sort_by{|fk| fk.describe}.map do |fk|
145
+ # Get the jump reference
146
+
147
+ if fk.from_columns.size > 1
148
+ raise "Can't emit Rails associations for multi-part foreign key with #{fk.references.inspect}. Did you mean to use --transform/surrogate"
149
+ end
150
+
151
+ association_type, association_name = *fk.rails_to_association
152
+
153
+ ref = fk.jump_reference
154
+ [
155
+ "\n \# #{fk.verbalised_path(true)}" +
156
+ "\n" +
157
+ %Q{ #{association_type} :#{association_name}} +
158
+ %Q{, :class_name => '#{fk.from.rails_class_name}'} +
159
+ %Q{, :foreign_key => :#{fk.from_columns[0].rails_name}} +
160
+ %Q{, :dependent => :destroy}
161
+ ] +
162
+ # If ref.from is a join table, we can emit a has_many :through for each other key
163
+ # REVISIT Could alternately do this for all belongs_to's in ref.from
164
+ if ref.from.identifier_columns.length > 1
165
+ ref.from.identifier_columns.map do |ic|
166
+ next nil if ic.references[0] == ref or # Skip the back-reference
167
+ ic.references[0].is_unary # or use rails_plural_name(ic.references[0].to_names) ?
168
+ # This far association name needs to be augmented for its role name
169
+ far_association_name = ic.references[0].to.rails_name
170
+ %Q{ has_many :#{far_association_name}, :through => :#{association_name}} # \# via #{ic.name}}
171
+ end
172
+ else
173
+ []
174
+ end
175
+ end.flatten.compact
176
+ end
177
+
178
+ def column_constraints table
179
+ return [] unless @validations
180
+ ccs =
181
+ table.columns.map do |column|
182
+ name = column.rails_name
183
+ column.is_mandatory &&
184
+ !column.is_auto_assigned && !column.is_auto_timestamp ? [
185
+ " validates :#{name}, :presence => true"
186
+ ] : []
187
+ end.flatten
188
+ ccs.unshift("") unless ccs.empty?
189
+ ccs
190
+ end
191
+
192
+ def model_body table
193
+ %Q{module #{table.rails_class_name}
194
194
  extend ActiveSupport::Concern
195
195
  included do} +
196
- (table.identifier_columns.length == 1 ? %Q{
196
+ (table.identifier_columns.length == 1 ? %Q{
197
197
  self.primary_key = '#{table.identifier_columns[0].rails_name}'
198
198
  } : ''
199
- ) +
200
-
201
- (
202
- to_associations(table) +
203
- from_associations(table) +
204
- column_constraints(table)
205
- ) * "\n" +
206
- %Q{
199
+ ) +
200
+
201
+ (
202
+ to_associations(table) +
203
+ from_associations(table) +
204
+ column_constraints(table)
205
+ ) * "\n" +
206
+ %Q{
207
207
  end
208
208
  end
209
209
  }
210
- end
210
+ end
211
211
 
212
- def generate_table table
213
- old_out = @out
214
- filename = table.rails_singular_name+'.rb'
212
+ def generate_table table
213
+ old_out = @out
214
+ filename = table.rails_singular_name+'.rb'
215
215
 
216
- return unless create_if_ok filename
216
+ return unless create_if_ok filename
217
217
 
218
- puts "\n"
219
- puts "module #{@concern}" if @concern
220
- puts model_body(table).gsub(/^./, @concern ? ' \0' : '\0')
221
- puts 'end' if @concern
218
+ puts "\n"
219
+ puts "module #{@concern}" if @concern
220
+ puts model_body(table).gsub(/^./, @concern ? ' \0' : '\0')
221
+ puts 'end' if @concern
222
222
 
223
- true # We succeeded
224
- ensure
225
- @out = old_out
226
- @individual_file.close if @individual_file
227
- end
223
+ true # We succeeded
224
+ ensure
225
+ @out = old_out
226
+ @individual_file.close if @individual_file
227
+ end
228
228
 
229
229
  end
230
230
  end
@@ -233,12 +233,12 @@ end
233
233
  module RMap
234
234
  class Column
235
235
  def is_auto_timestamp
236
- case name('_')
237
- when /\A(created|updated)_(at|on)\Z/i
238
- true
239
- else
240
- false
241
- end
236
+ case name('_')
237
+ when /\A(created|updated)_(at|on)\Z/i
238
+ true
239
+ else
240
+ false
241
+ end
242
242
  end
243
243
  end
244
244
  end
@@ -17,197 +17,197 @@ module ActiveFacts
17
17
  # afgen --rails/schema[=options] <file>.cql
18
18
  class SchemaRb
19
19
  private
20
- include RMap
21
-
22
- def initialize(vocabulary, *options)
23
- @vocabulary = vocabulary
24
- @vocabulary = @vocabulary.Vocabulary.values[0] if ActiveFacts::API::Constellation === @vocabulary
25
- help if options.include? "help"
26
- @exclude_fks = options.include? "exclude_fks"
27
- @include_comments = options.include? "include_comments"
28
- @closed_world = options.include? "closed_world"
29
- end
30
-
31
- def help
32
- @helping = true
33
- warn %Q{Options for --rails/schema:
34
- exclude_fks Don't generate foreign key definitions for use with Rails 4 or the foreigner gem
35
- include_comments Generate a comment for each column showing the absorption path
36
- closed_world Set this if your DBMS only allows one null in a unique index (MS SQL)
20
+ include RMap
21
+
22
+ def initialize(vocabulary, *options)
23
+ @vocabulary = vocabulary
24
+ @vocabulary = @vocabulary.Vocabulary.values[0] if ActiveFacts::API::Constellation === @vocabulary
25
+ help if options.include? "help"
26
+ @exclude_fks = options.include? "exclude_fks"
27
+ @include_comments = options.include? "include_comments"
28
+ @closed_world = options.include? "closed_world"
29
+ end
30
+
31
+ def help
32
+ @helping = true
33
+ warn %Q{Options for --rails/schema:
34
+ exclude_fks Don't generate foreign key definitions for use with Rails 4 or the foreigner gem
35
+ include_comments Generate a comment for each column showing the absorption path
36
+ closed_world Set this if your DBMS only allows one null in a unique index (MS SQL)
37
37
  }
38
- end
38
+ end
39
39
 
40
- def warn *a
41
- $stderr.puts *a
42
- end
40
+ def warn *a
41
+ $stderr.puts *a
42
+ end
43
43
 
44
- def puts s
45
- @out.puts s
46
- end
44
+ def puts s
45
+ @out.puts s
46
+ end
47
47
 
48
48
  public
49
49
 
50
- # We sort the columns here, not in the rmap layer, because it affects
51
- # the ordering of columns in an index :-(.
52
- def sorted_columns table, pk, fk_columns
53
- table.columns.sort_by do |column|
54
- [ # Emit columns alphabetically, but PK first, then FKs, then others
55
- case
56
- when i = pk.index(column)
57
- i
58
- when fk_columns.include?(column)
59
- pk.size+1
60
- else
61
- pk.size+2
62
- end,
63
- column.rails_name
64
- ]
65
- end
66
- end
67
-
68
- def generate_column table, pk, column
69
- name = column.rails_name
70
- type, params, constraints = *column.type
71
- length = params[:length]
72
- length &&= length.to_i
73
- scale = params[:scale]
74
- scale &&= scale.to_i
75
- rails_type, length = *column.rails_type
50
+ # We sort the columns here, not in the rmap layer, because it affects
51
+ # the ordering of columns in an index :-(.
52
+ def sorted_columns table, pk, fk_columns
53
+ table.columns.sort_by do |column|
54
+ [ # Emit columns alphabetically, but PK first, then FKs, then others
55
+ case
56
+ when i = pk.index(column)
57
+ i
58
+ when fk_columns.include?(column)
59
+ pk.size+1
60
+ else
61
+ pk.size+2
62
+ end,
63
+ column.rails_name
64
+ ]
65
+ end
66
+ end
67
+
68
+ def generate_column table, pk, column
69
+ name = column.rails_name
70
+ type, params, constraints = *column.type
71
+ length = params[:length]
72
+ length &&= length.to_i
73
+ scale = params[:scale]
74
+ scale &&= scale.to_i
75
+ rails_type, length = *column.rails_type
76
76
 
77
- length_name = rails_type == 'decimal' ? 'precision' : 'limit'
78
- length_option = length ? ", :#{length_name} => #{length}" : ''
79
- scale_option = scale ? ", :scale => #{scale}" : ''
80
-
81
- comment = column.comment
82
- null_option = ", :null => #{!column.is_mandatory}"
83
- if pk.size == 1 && pk[0] == column
84
- case rails_type
85
- when 'serial'
86
- rails_type = "primary_key"
87
- when 'uuid'
88
- rails_type = "uuid, :default => 'gen_random_uuid()', :primary_key => true"
89
- end
90
- else
91
- case rails_type
92
- when 'serial'
93
- rails_type = 'integer' # An integer foreign key
94
- end
95
- end
96
-
97
- (@include_comments ? [" \# #{comment}"] : []) +
98
- [
99
- %Q{ t.column "#{name}", :#{rails_type}#{length_option}#{scale_option}#{null_option}}
100
- ]
101
- end
102
-
103
- def generate_columns table, pk, fk_columns
104
- sc = sorted_columns(table, pk, fk_columns)
105
- lines = sc.map do |column|
106
- generate_column table, pk, column
107
- end
108
- lines.flatten
109
- end
110
-
111
- def generate_table table, foreign_keys
112
- ar_table_name = table.rails_name
113
-
114
- pk = table.identifier_columns
115
- if pk[0].is_auto_assigned
116
- identity_column = pk[0]
117
- warn "Warning: redundant column(s) after #{identity_column.name} in primary key of #{ar_table_name}" if pk.size > 1
118
- end
119
-
120
- # Get the list of references that give rise to foreign keys:
121
- fk_refs = table.references_from.select{|ref| ref.is_simple_reference }
122
-
123
- # Get the list of columns that embody the foreign keys:
124
- fk_columns = table.columns.select do |column|
125
- column.references[0].is_simple_reference
126
- end
127
-
128
- # Detect if this table is a join table.
129
- # Join tables have multi-part primary keys that are made up only of foreign keys
130
- is_join_table = pk.length > 1 and
131
- !pk.detect do |pk_column|
132
- !fk_columns.include?(pk_column)
133
- end
134
- warn "Warning: #{table.name} has a multi-part primary key" if pk.length > 1 and !is_join_table
135
-
136
- puts %Q{ create_table "#{ar_table_name}", :id => false, :force => true do |t|}
137
-
138
- columns = generate_columns table, pk, fk_columns
139
-
140
- unless @exclude_fks
141
- table.foreign_keys.each do |fk|
142
- from_columns = fk.from_columns.map{|column| column.rails_name}
143
- to_columns = fk.to_columns.map{|column| column.rails_name}
144
-
145
- foreign_keys.concat(
146
- if (from_columns.length == 1)
147
- index_name = RMap.rails_name_trunc('index_'+fk.from.rails_name+'_on_'+from_columns[0])
148
- [
149
- " add_foreign_key :#{fk.from.rails_name}, :#{fk.to.rails_name}, :column => :#{from_columns[0]}, :primary_key => :#{to_columns[0]}, :on_delete => :cascade"
150
- ]+
151
- Array(
152
- # Index it non-uniquely only if it's not unique already:
153
- fk.jump_reference.to_role.is_unique ? nil :
154
- " add_index :#{fk.from.rails_name}, [:#{from_columns[0]}], :unique => false, :name => :#{index_name}"
155
- )
156
- else
157
- # This probably isn't going to work without Dr Nic's CPK gem:
158
- [
159
- " add_foreign_key :#{fk.to.rails_name}, :#{fk.from.rails_name}, :column => [:#{from_columns.join(':, ')}], :primary_key => [:#{to_columns.join(':, ')}], :on_delete => :cascade"
160
- ]
161
- end
162
- )
163
- end
164
- end
165
-
166
- indices = table.indices
167
- index_text = []
168
- indices.each do |index|
169
- next if index.is_primary && index.columns.size == 1 # We've handled this already
170
-
171
- index_name = index.rails_name
172
-
173
- unique = !index.columns.detect{|column| !column.is_mandatory} and !@closed_world
174
- index_text << %Q{ add_index "#{ar_table_name}", ["#{index.columns.map{|c| c.rails_name}*'", "'}"], :name => :#{index_name}#{
175
- unique ? ", :unique => true" : ''
176
- }}
177
- end
178
-
179
- puts columns.join("\n")
180
- puts " end\n\n"
181
-
182
- puts index_text.join("\n")
183
- puts "\n" unless index_text.empty?
184
- end
185
-
186
- def generate(out = $>) #:nodoc:
187
- return if @helping
188
- @out = out
189
-
190
- foreign_keys = []
191
-
192
- # If we get index names that need to be truncated, add a counter to ensure uniqueness
193
- dup_id = 0
194
-
195
- puts "#\n# schema.rb auto-generated using ActiveFacts for #{@vocabulary.name} on #{Date.today}\n#\n\n"
196
- puts "ActiveRecord::Base.logger = Logger.new(STDOUT)\n"
197
- puts "ActiveRecord::Schema.define(:version => #{Time.now.strftime('%Y%m%d%H%M%S')}) do"
198
- puts " enable_extension 'pgcrypto' unless extension_enabled?('pgcrypto')\n"
199
-
200
- @vocabulary.tables.each do |table|
201
- generate_table table, foreign_keys
202
- end
203
-
204
- unless @exclude_fks
205
- puts ' unless ENV["EXCLUDE_FKS"]'
206
- puts foreign_keys.join("\n")
207
- puts ' end'
208
- end
209
- puts "end"
210
- end
77
+ length_name = rails_type == 'decimal' ? 'precision' : 'limit'
78
+ length_option = length ? ", #{length_name}: #{length}" : ''
79
+ scale_option = scale ? ", scale: #{scale}" : ''
80
+
81
+ comment = column.comment
82
+ null_option = ", null: #{!column.is_mandatory}"
83
+ if pk.size == 1 && pk[0] == column
84
+ case rails_type
85
+ when 'serial'
86
+ rails_type = "primary_key"
87
+ when 'uuid'
88
+ rails_type = "uuid, default: 'gen_random_uuid()', primary_key: true"
89
+ end
90
+ else
91
+ case rails_type
92
+ when 'serial'
93
+ rails_type = 'integer' # An integer foreign key
94
+ end
95
+ end
96
+
97
+ (@include_comments ? [" \# #{comment}"] : []) +
98
+ [
99
+ %Q{ t.column "#{name}", :#{rails_type}#{length_option}#{scale_option}#{null_option}}
100
+ ]
101
+ end
102
+
103
+ def generate_columns table, pk, fk_columns
104
+ sc = sorted_columns(table, pk, fk_columns)
105
+ lines = sc.map do |column|
106
+ generate_column table, pk, column
107
+ end
108
+ lines.flatten
109
+ end
110
+
111
+ def generate_table table, foreign_keys
112
+ ar_table_name = table.rails_name
113
+
114
+ pk = table.identifier_columns
115
+ if pk[0].is_auto_assigned
116
+ identity_column = pk[0]
117
+ warn "Warning: redundant column(s) after #{identity_column.name} in primary key of #{ar_table_name}" if pk.size > 1
118
+ end
119
+
120
+ # Get the list of references that give rise to foreign keys:
121
+ fk_refs = table.references_from.select{|ref| ref.is_simple_reference }
122
+
123
+ # Get the list of columns that embody the foreign keys:
124
+ fk_columns = table.columns.select do |column|
125
+ column.references[0].is_simple_reference
126
+ end
127
+
128
+ # Detect if this table is a join table.
129
+ # Join tables have multi-part primary keys that are made up only of foreign keys
130
+ is_join_table = pk.length > 1 and
131
+ !pk.detect do |pk_column|
132
+ !fk_columns.include?(pk_column)
133
+ end
134
+ warn "Warning: #{table.name} has a multi-part primary key" if pk.length > 1 and !is_join_table
135
+
136
+ puts %Q{ create_table "#{ar_table_name}", id: false, force: true do |t|}
137
+
138
+ columns = generate_columns table, pk, fk_columns
139
+
140
+ unless @exclude_fks
141
+ table.foreign_keys.each do |fk|
142
+ from_columns = fk.from_columns.map{|column| column.rails_name}
143
+ to_columns = fk.to_columns.map{|column| column.rails_name}
144
+
145
+ foreign_keys.concat(
146
+ if (from_columns.length == 1)
147
+ index_name = RMap.rails_name_trunc('index_'+fk.from.rails_name+'_on_'+from_columns[0])
148
+ [
149
+ " add_foreign_key :#{fk.from.rails_name}, :#{fk.to.rails_name}, column: :#{from_columns[0]}, primary_key: :#{to_columns[0]}, on_delete: :cascade"
150
+ ]+
151
+ Array(
152
+ # Index it non-uniquely only if it's not unique already:
153
+ fk.jump_reference.to_role.is_unique ? nil :
154
+ " add_index :#{fk.from.rails_name}, [:#{from_columns[0]}], unique: false, name: :#{index_name}"
155
+ )
156
+ else
157
+ # This probably isn't going to work without Dr Nic's CPK gem:
158
+ [
159
+ " add_foreign_key :#{fk.to.rails_name}, :#{fk.from.rails_name}, column: [:#{from_columns.join(':, ')}], primary_key: [:#{to_columns.join(':, ')}], on_delete: :cascade"
160
+ ]
161
+ end
162
+ )
163
+ end
164
+ end
165
+
166
+ indices = table.indices
167
+ index_text = []
168
+ indices.each do |index|
169
+ next if index.is_primary && index.columns.size == 1 # We've handled this already
170
+
171
+ index_name = index.rails_name
172
+
173
+ unique = !index.columns.detect{|column| !column.is_mandatory} and !@closed_world
174
+ index_text << %Q{ add_index "#{ar_table_name}", ["#{index.columns.map{|c| c.rails_name}*'", "'}"], name: :#{index_name}#{
175
+ unique ? ", unique: true" : ''
176
+ }}
177
+ end
178
+
179
+ puts columns.join("\n")
180
+ puts " end\n\n"
181
+
182
+ puts index_text.join("\n")
183
+ puts "\n" unless index_text.empty?
184
+ end
185
+
186
+ def generate(out = $>) #:nodoc:
187
+ return if @helping
188
+ @out = out
189
+
190
+ foreign_keys = []
191
+
192
+ # If we get index names that need to be truncated, add a counter to ensure uniqueness
193
+ dup_id = 0
194
+
195
+ puts "#\n# schema.rb auto-generated using ActiveFacts for #{@vocabulary.name} on #{Date.today}\n#\n\n"
196
+ puts "ActiveRecord::Base.logger = Logger.new(STDOUT)\n"
197
+ puts "ActiveRecord::Schema.define(version: #{Time.now.strftime('%Y%m%d%H%M%S')}) do"
198
+ puts " enable_extension 'pgcrypto' unless extension_enabled?('pgcrypto')\n"
199
+
200
+ @vocabulary.tables.each do |table|
201
+ generate_table table, foreign_keys
202
+ end
203
+
204
+ unless @exclude_fks
205
+ puts ' unless ENV["EXCLUDE_FKS"]'
206
+ puts foreign_keys.join("\n")
207
+ puts ' end'
208
+ end
209
+ puts "end"
210
+ end
211
211
 
212
212
  end
213
213
  end
@@ -195,6 +195,9 @@ module ActiveFacts
195
195
  :fact_type => ref.fact_type,
196
196
  :concept => :new
197
197
  )
198
+
199
+ # REVISIT: Objectifying requires creation of LinkFactTypes.
200
+
198
201
  @link_tables << et
199
202
  end
200
203
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activefacts-generators
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.2
4
+ version: 1.8.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clifford Heath
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-16 00:00:00.000000000 Z
11
+ date: 2016-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -17,9 +17,6 @@ dependencies:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.10'
20
- - - "~>"
21
- - !ruby/object:Gem::Version
22
- version: 1.10.6
23
20
  type: :development
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
@@ -27,9 +24,6 @@ dependencies:
27
24
  - - ">="
28
25
  - !ruby/object:Gem::Version
29
26
  version: '1.10'
30
- - - "~>"
31
- - !ruby/object:Gem::Version
32
- version: 1.10.6
33
27
  - !ruby/object:Gem::Dependency
34
28
  name: rake
35
29
  requirement: !ruby/object:Gem::Requirement