activefacts-compositions 1.9.22 → 1.9.23
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +1 -1
- data/activefacts-compositions.gemspec +1 -1
- data/bin/schema_compositor +71 -27
- data/lib/activefacts/compositions/binary.rb +4 -0
- data/lib/activefacts/compositions/datavault.rb +4 -0
- data/lib/activefacts/compositions/relational.rb +4 -0
- data/lib/activefacts/compositions/staging.rb +4 -0
- data/lib/activefacts/compositions/version.rb +1 -1
- data/lib/activefacts/generator/doc/css/glossary-print.css +72 -0
- data/lib/activefacts/generator/doc/css/glossary.css +194 -0
- data/lib/activefacts/generator/doc/css/ldm.css +12 -17
- data/lib/activefacts/generator/doc/css/orm2-print.css +19 -0
- data/lib/activefacts/generator/doc/css/orm2.css +28 -0
- data/lib/activefacts/generator/doc/css/reset.css +18 -0
- data/lib/activefacts/generator/doc/css/treetable.css +83 -0
- data/lib/activefacts/generator/doc/cwm.rb +60 -54
- data/lib/activefacts/generator/doc/glossary.rb +261 -137
- data/lib/activefacts/generator/doc/graphviz.rb +6 -2
- data/lib/activefacts/generator/doc/ldm.rb +7 -3
- data/lib/activefacts/generator/etl/unidex.rb +7 -2
- data/lib/activefacts/generator/oo.rb +2 -1
- data/lib/activefacts/generator/population.rb +174 -0
- data/lib/activefacts/generator/rails/active_admin.rb +81 -0
- data/lib/activefacts/generator/rails/application_record_shell.rb +78 -0
- data/lib/activefacts/generator/rails/models.rb +31 -72
- data/lib/activefacts/generator/rails/ruby_folder_generator.rb +87 -0
- data/lib/activefacts/generator/rails/schema.rb +12 -4
- data/lib/activefacts/generator/ruby.rb +7 -3
- data/lib/activefacts/generator/sql.rb +2 -1
- data/lib/activefacts/generator/summary.rb +24 -19
- data/lib/activefacts/generator/traits/sql.rb +4 -0
- data/lib/activefacts/generator/transgen.rb +7 -1
- data/lib/activefacts/generator/validate.rb +10 -2
- metadata +15 -5
@@ -19,8 +19,12 @@ module ActiveFacts
|
|
19
19
|
}
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
|
22
|
+
def self.compatibility
|
23
|
+
[1, nil] # one composition of ny kind
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize constellation, composition, options = {}
|
27
|
+
@constellation = constellation
|
24
28
|
@composition = compositions[0]
|
25
29
|
@options = options
|
26
30
|
end
|
@@ -21,9 +21,13 @@ module ActiveFacts
|
|
21
21
|
}
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
24
|
+
def self.compatibility
|
25
|
+
[1, %i{relational}] # one relational composition
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize constellation, composition, options = {}
|
29
|
+
@constellation = constellation
|
30
|
+
@composition = [composition].flatten[0]
|
27
31
|
@options = options
|
28
32
|
@underscore = options.has_key?("underscore") ? (options['underscore'] || '_') : ''
|
29
33
|
|
@@ -15,7 +15,6 @@ module ActiveFacts
|
|
15
15
|
module Generators
|
16
16
|
module ETL
|
17
17
|
class Unidex
|
18
|
-
|
19
18
|
MM = ActiveFacts::Metamodel unless const_defined?(:MM)
|
20
19
|
def self.options
|
21
20
|
# REVISIT: There's no way to support SQL dialect options here
|
@@ -29,7 +28,13 @@ module ActiveFacts
|
|
29
28
|
)
|
30
29
|
end
|
31
30
|
|
32
|
-
def
|
31
|
+
def self.compatibility
|
32
|
+
# REVISIT: Remove the dependency on the "persistent" option of the staging compositor.
|
33
|
+
[1, %i{relational}] # one relational composition
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize constellation, composition, options = {}
|
37
|
+
@constellation = constellation
|
33
38
|
@composition = composition
|
34
39
|
@options = options
|
35
40
|
|
@@ -18,7 +18,8 @@ module ActiveFacts
|
|
18
18
|
}
|
19
19
|
end
|
20
20
|
|
21
|
-
def initialize composition, options = {}
|
21
|
+
def initialize constellation, composition, options = {}
|
22
|
+
@constellation = constellation
|
22
23
|
@composition = composition
|
23
24
|
@options = options
|
24
25
|
@comments = @options.delete("comments")
|
@@ -0,0 +1,174 @@
|
|
1
|
+
#
|
2
|
+
# ActiveFacts Population Generator
|
3
|
+
#
|
4
|
+
# Copyright (c) 2018 Clifford Heath. Read the LICENSE file.
|
5
|
+
#
|
6
|
+
require 'digest/sha1'
|
7
|
+
require 'activefacts/metamodel'
|
8
|
+
require 'activefacts/metamodel/datatypes'
|
9
|
+
require 'activefacts/compositions'
|
10
|
+
require 'activefacts/compositions/names'
|
11
|
+
require 'activefacts/generator'
|
12
|
+
require 'activefacts/generator/traits/sql'
|
13
|
+
|
14
|
+
module ActiveFacts
|
15
|
+
module Generators
|
16
|
+
class Population
|
17
|
+
|
18
|
+
MM = ActiveFacts::Metamodel unless const_defined?(:MM)
|
19
|
+
def self.options
|
20
|
+
# REVISIT: There's no way to support SQL dialect options here
|
21
|
+
sql_trait = ActiveFacts::Generators::Traits::SQL
|
22
|
+
Class.new.extend(sql_trait). # Anonymous class to enable access to traits module instance methods
|
23
|
+
options.
|
24
|
+
merge(
|
25
|
+
{
|
26
|
+
dialect: [String, "SQL Dialect to use"],
|
27
|
+
population: [String, "Name of the fact population to process (defaults to anonymous seed population)"],
|
28
|
+
}
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.compatibility
|
33
|
+
[1, %i{relational}] # one relational composition
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize constellation, composition, options = {}
|
37
|
+
@constellation = constellation
|
38
|
+
@composition = composition
|
39
|
+
@options = options
|
40
|
+
|
41
|
+
@trait = ActiveFacts::Generators::Traits::SQL
|
42
|
+
if @dialect = options.delete("dialect")
|
43
|
+
require 'activefacts/generator/traits/sql/'+@dialect
|
44
|
+
trait_name = ActiveFacts::Generators::Traits::SQL.constants.detect{|c| c.to_s =~ %r{#{@dialect}}i}
|
45
|
+
@trait = @trait.const_get(trait_name)
|
46
|
+
end
|
47
|
+
self.class.include @trait
|
48
|
+
self.class.extend @trait
|
49
|
+
extend @trait
|
50
|
+
@population_name = options.delete("population") || ''
|
51
|
+
|
52
|
+
process_options options
|
53
|
+
end
|
54
|
+
|
55
|
+
def process_options options
|
56
|
+
super
|
57
|
+
end
|
58
|
+
|
59
|
+
def generate
|
60
|
+
@constellation = @composition.constellation
|
61
|
+
@vocabulary = @constellation.Vocabulary.values[0]
|
62
|
+
@population = @constellation.Population[[[@vocabulary.name], @population_name]]
|
63
|
+
raise "Population #{@population_name.inspect} doesn't exist in #{@vocabulary.name.inspect}" unless @population_name
|
64
|
+
@composites = @composition.all_composite.select{|c| c.mapping.object_type.all_instance.size > 0}
|
65
|
+
header +
|
66
|
+
@composites.
|
67
|
+
map{|c| generate_composite c}.
|
68
|
+
compact*"\n\n" +
|
69
|
+
trailer
|
70
|
+
end
|
71
|
+
|
72
|
+
def header
|
73
|
+
schema_prefix
|
74
|
+
end
|
75
|
+
|
76
|
+
def generate_composite composite
|
77
|
+
leaf_column_names = composite.mapping.all_leaf.map do |leaf|
|
78
|
+
[leaf, safe_column_name(leaf)]
|
79
|
+
end
|
80
|
+
|
81
|
+
"-- #{composite.mapping.name}\n" +
|
82
|
+
composite.mapping.object_type.all_instance.map do |instance|
|
83
|
+
ncv = named_column_values leaf_column_names, instance
|
84
|
+
%Q{INSERT INTO #{safe_table_name composite}(#{ncv.map{|name, value|name}*', '})\n} +
|
85
|
+
%Q{\tVALUES (#{ncv.map{|name, value| value}*', '});}
|
86
|
+
end.sort * "\n"
|
87
|
+
end
|
88
|
+
|
89
|
+
def named_column_values leaf_column_names, instance
|
90
|
+
leaf_column_names.map do |leaf, column_name|
|
91
|
+
current = instance
|
92
|
+
value = nil
|
93
|
+
leaf.path[1..-1].each do |component|
|
94
|
+
trace :population, "Traversing #{component.inspect}" do
|
95
|
+
case component
|
96
|
+
when MM::Absorption # Fact
|
97
|
+
fact_type = component.parent_role.fact_type
|
98
|
+
trace :population, "Fact Type #{fact_type.default_reading}"
|
99
|
+
|
100
|
+
if MM::LinkFactType === fact_type
|
101
|
+
# Populations do not contain LinkFactTypes for an Objectified Fact Type,
|
102
|
+
# but Compositions use them. The child_role is probably a mirror role.
|
103
|
+
role = fact_type.implying_role # This is the real role
|
104
|
+
fact_type = role.fact_type # And this is the real fact
|
105
|
+
raise "Internal error finding objectified fact" if instance.fact.fact_type != fact_type
|
106
|
+
role_value = fact.all_role_value{|rv| rv.role == role}
|
107
|
+
else
|
108
|
+
role_values = instance.all_role_value.select{|rv| rv.population == @population && rv.fact.fact_type == fact_type}
|
109
|
+
raise "Population contains duplicate fact for #{fact_type.default_reading.inspect} in violation of uniqueness constraint" if role_values.size > 1
|
110
|
+
if role_values.empty?
|
111
|
+
trace :population, "No fact is present"
|
112
|
+
break
|
113
|
+
end
|
114
|
+
residual_rvs = role_values[0].fact.all_role_value.to_a-[role_values[0]]
|
115
|
+
raise "Instance of #{fact_type.default_reading.inspect} lacks some role players" unless residual_rvs.size == fact_type.all_role.size-1
|
116
|
+
if residual_rvs.size != 1
|
117
|
+
raise "Internal error in fact population, n-ary fact type #{fact_type.default_reading}"
|
118
|
+
end
|
119
|
+
role_value = residual_rvs[0]
|
120
|
+
end
|
121
|
+
|
122
|
+
current = role_value.instance
|
123
|
+
trace :population, "Instance is #{current.object_type.name}#{current.value ? ' = '+current.value.inspect : ''}"
|
124
|
+
value = current.value.inspect
|
125
|
+
|
126
|
+
when MM::Indicator
|
127
|
+
fact_type = component.role.fact_type
|
128
|
+
trace :population, "Fact Type #{fact_type.default_reading}"
|
129
|
+
role_values = instance.all_role_value.select{|rv| rv.population == @population && rv.fact.fact_type == fact_type}
|
130
|
+
raise "Population contains duplicate fact for #{fact_type.default_reading.inspect} in violation of uniqueness constraint" if role_values.size > 1
|
131
|
+
value = true
|
132
|
+
|
133
|
+
when MM::ValueField
|
134
|
+
# The value is the value of the Value Type
|
135
|
+
value = current.value.inspect
|
136
|
+
|
137
|
+
when MM::Discriminator
|
138
|
+
# The value depends on which of the discriminated roles are played (must be only one)
|
139
|
+
raise "Cannot emit population containing a Discriminator, not implemented"
|
140
|
+
drs = component.all_discriminated_role.select{|dr| instance.all_role_value.detect{|rv| rv.role == dr.role}}
|
141
|
+
raise "Discriminator has ambiguous value, with more than one candidate role" if drs.size > 1
|
142
|
+
value = drs[0].value.inspect if drs[0]
|
143
|
+
|
144
|
+
# The following types are not conceptual so will never have asserted facts
|
145
|
+
when MM::Injection,
|
146
|
+
MM::Scoping,
|
147
|
+
MM::SurrogateKey,
|
148
|
+
MM::ValidFrom,
|
149
|
+
MM::Mapping,
|
150
|
+
MM::ComputedValue,
|
151
|
+
MM::HashValue
|
152
|
+
break
|
153
|
+
|
154
|
+
else
|
155
|
+
raise "Unhandled Component type #{component.class.name} in composition"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
value ? [column_name, value] : nil
|
160
|
+
end.compact
|
161
|
+
end
|
162
|
+
|
163
|
+
def trailer
|
164
|
+
''
|
165
|
+
end
|
166
|
+
|
167
|
+
def stylise_column_name name
|
168
|
+
name.words.send(@column_case)*@column_joiner
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
publish_generator Population, "Generate SQL to insert or update records defined as a fact population"
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#
|
2
|
+
# ActiveFacts Admin App Generator
|
3
|
+
#
|
4
|
+
# Copyright (c) 2018 Daniel Heath. Read the LICENSE file.
|
5
|
+
#
|
6
|
+
require 'digest/sha1'
|
7
|
+
require 'activefacts/metamodel'
|
8
|
+
require 'activefacts/compositions'
|
9
|
+
require 'activefacts/generator'
|
10
|
+
require 'activefacts/compositions/traits/rails'
|
11
|
+
require 'activefacts/generator/rails/ruby_folder_generator'
|
12
|
+
|
13
|
+
module ActiveFacts
|
14
|
+
module Generators
|
15
|
+
module Rails
|
16
|
+
class ActiveAdmin
|
17
|
+
include RubyFolderGenerator
|
18
|
+
def self.options
|
19
|
+
({
|
20
|
+
keep: ['Boolean', "Keep stale files"],
|
21
|
+
output: [String, "Write admin config files into this output directory"],
|
22
|
+
})
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.compatibility
|
26
|
+
# REVISIT: We depend on the surrogate option being enabled if any PK is not Rails-friendly
|
27
|
+
[1, %i{relational}] # one relational composition
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize constellation, composition, options = {}
|
31
|
+
@constellation = constellation
|
32
|
+
@composition = composition
|
33
|
+
@options = options
|
34
|
+
@option_keep = options.delete("keep")
|
35
|
+
@option_output = options.delete("output")
|
36
|
+
@option_output ||= 'app/admin'
|
37
|
+
@option_output = nil if @option_output == "-"
|
38
|
+
end
|
39
|
+
|
40
|
+
def generate_files
|
41
|
+
admins =
|
42
|
+
@composition.
|
43
|
+
all_composite.
|
44
|
+
sort_by {|composite| composite.mapping.name}.
|
45
|
+
reject {|composite| composite.mapping.object_type.is_static}.
|
46
|
+
map {|composite| generate_admin composite}.
|
47
|
+
compact * "\n"
|
48
|
+
end
|
49
|
+
|
50
|
+
def extant_files
|
51
|
+
Dir[@option_output+'/*.rb']
|
52
|
+
end
|
53
|
+
|
54
|
+
def generate_admin composite
|
55
|
+
columns = composite.mapping.all_leaf.flat_map do |component|
|
56
|
+
# Absorbed empty subtypes appear as leaves
|
57
|
+
next [] if component.is_a?(MM::Absorption) && component.parent_role.fact_type.is_a?(MM::TypeInheritance)
|
58
|
+
':' + component.column_name.snakecase
|
59
|
+
end
|
60
|
+
|
61
|
+
model = "ActiveAdmin.register #{composite.rails.class_name} do\n permit_params #{columns.join(', ')}\nend\n"
|
62
|
+
|
63
|
+
return model unless @option_output
|
64
|
+
|
65
|
+
filename = composite.rails.singular_name+'_admin.rb'
|
66
|
+
out = create_if_ok(@option_output, filename)
|
67
|
+
return nil unless out
|
68
|
+
out.puts "#{HEADER}\n" +
|
69
|
+
"\# #{([File.basename($0)]+ARGV)*' '}\n\n" +
|
70
|
+
model
|
71
|
+
ensure
|
72
|
+
out.close if out
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
|
76
|
+
MM = ActiveFacts::Metamodel unless const_defined?(:MM)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
publish_generator Rails::ActiveAdmin, "Generate models in Ruby for use with ActiveAdmin and Rails. Use a relational compositor"
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
#
|
2
|
+
# ActiveFacts Rails Models Generator
|
3
|
+
#
|
4
|
+
# Copyright (c) 2009-2016 Daniel Heath. Read the LICENSE file.
|
5
|
+
#
|
6
|
+
require 'digest/sha1'
|
7
|
+
require 'activefacts/metamodel'
|
8
|
+
require 'activefacts/compositions'
|
9
|
+
require 'activefacts/generator'
|
10
|
+
require 'activefacts/compositions/traits/rails'
|
11
|
+
require 'activefacts/generator/rails/ruby_folder_generator'
|
12
|
+
|
13
|
+
module ActiveFacts
|
14
|
+
module Generators
|
15
|
+
module Rails
|
16
|
+
class ApplicationRecordShell
|
17
|
+
include RubyFolderGenerator
|
18
|
+
def self.options
|
19
|
+
({
|
20
|
+
keep: ['Boolean', "Keep stale model files"],
|
21
|
+
validation: ['Boolean', "Disable generation of validations"],
|
22
|
+
concern: [String, "Namespace for the concerns"],
|
23
|
+
output: [String, "Generate models in given directory (as well as concerns)"],
|
24
|
+
})
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.compatibility
|
28
|
+
# REVISIT: We depend on the surrogate option being enabled if any PK is not Rails-friendly
|
29
|
+
[1, %i{relational}] # one relational composition
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize constellation, composition, options = {}
|
33
|
+
@constellation = constellation
|
34
|
+
@composition = composition
|
35
|
+
@options = options
|
36
|
+
@option_keep = options.delete("keep")
|
37
|
+
@option_concern = options.delete("concern")
|
38
|
+
|
39
|
+
@option_output = options.delete("output")
|
40
|
+
if !@option_output
|
41
|
+
@option_output = "app/models"
|
42
|
+
end
|
43
|
+
@option_output = nil if @option_output == "-" # dash for stdout
|
44
|
+
end
|
45
|
+
|
46
|
+
def generate_files
|
47
|
+
@composition.
|
48
|
+
all_composite.
|
49
|
+
sort_by{|composite| composite.mapping.name}.
|
50
|
+
map{|composite| generate_model composite}.
|
51
|
+
compact*"\n"
|
52
|
+
end
|
53
|
+
|
54
|
+
def extant_files
|
55
|
+
Dir[@option_output+'/*.rb'] if @option_output
|
56
|
+
end
|
57
|
+
|
58
|
+
def generate_model composite
|
59
|
+
concern_module = @option_concern ? "#{@option_concern}::" : ""
|
60
|
+
model = "class #{composite.rails.class_name} < ApplicationRecord\n include #{concern_module}#{composite.rails.class_name}\nend\n"
|
61
|
+
|
62
|
+
return model unless @option_output
|
63
|
+
|
64
|
+
filename = composite.rails.singular_name+'.rb'
|
65
|
+
out = create_if_ok(@option_output, filename)
|
66
|
+
return nil unless out
|
67
|
+
out.puts "#{HEADER}\n" +
|
68
|
+
"\# #{([File.basename($0)]+ARGV)*' '}\n\n" +
|
69
|
+
model
|
70
|
+
ensure
|
71
|
+
out.close if out
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
publish_generator Rails::ApplicationRecordShell, "Generate ApplicationRecord shell in Ruby for use with ActiveRecord and Rails. Use a relational compositor"
|
77
|
+
end
|
78
|
+
end
|
@@ -8,96 +8,53 @@ require 'activefacts/metamodel'
|
|
8
8
|
require 'activefacts/compositions'
|
9
9
|
require 'activefacts/generator'
|
10
10
|
require 'activefacts/compositions/traits/rails'
|
11
|
+
require 'activefacts/generator/rails/ruby_folder_generator'
|
11
12
|
|
12
13
|
module ActiveFacts
|
13
14
|
module Generators
|
14
15
|
module Rails
|
15
16
|
class Models
|
16
|
-
|
17
|
+
include RubyFolderGenerator
|
17
18
|
def self.options
|
18
19
|
({
|
19
|
-
keep:
|
20
|
-
output:
|
21
|
-
concern:
|
22
|
-
validation:
|
20
|
+
keep: ['Boolean', "Keep stale model files"],
|
21
|
+
output: [String, "Overwrite model files into this output directory"],
|
22
|
+
concern: [String, "Namespace for the concerns"],
|
23
|
+
validation: ['Boolean', "Disable generation of validations"],
|
23
24
|
})
|
24
25
|
end
|
25
26
|
|
26
|
-
def
|
27
|
+
def self.compatibility
|
28
|
+
# REVISIT: We depend on the surrogate option being enabled if any PK is not Rails-friendly
|
29
|
+
[1, %i{relational}] # one relational composition
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize constellation, composition, options = {}
|
33
|
+
@constellation = constellation
|
27
34
|
@composition = composition
|
28
35
|
@options = options
|
29
36
|
@option_keep = options.delete("keep")
|
30
|
-
@option_output = options.delete("output")
|
31
37
|
@option_concern = options.delete("concern")
|
32
|
-
@option_validations = options.include?('validations') ? options.delete("validations") : true
|
33
|
-
end
|
34
|
-
|
35
|
-
def warn *a
|
36
|
-
$stderr.puts *a
|
37
|
-
end
|
38
|
-
|
39
|
-
def generate
|
40
|
-
list_extant_files if @option_output && !@option_keep
|
41
|
-
|
42
|
-
@ok = true
|
43
|
-
models =
|
44
|
-
@composition.
|
45
|
-
all_composite.
|
46
|
-
sort_by{|composite| composite.mapping.name}.
|
47
|
-
map{|composite| generate_composite composite}.
|
48
|
-
compact*"\n"
|
49
|
-
|
50
|
-
warn "\# #{@composition.name} generated with errors" unless @ok
|
51
|
-
delete_old_generated_files if @option_output && !@option_keep
|
52
|
-
|
53
|
-
models
|
54
|
-
end
|
55
38
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
def delete_old_generated_files
|
61
|
-
remaining = []
|
62
|
-
cleaned = 0
|
63
|
-
@preexisting_files.each do |pathname|
|
64
|
-
if generated_file_exists(pathname) == true
|
65
|
-
File.unlink(pathname)
|
66
|
-
cleaned += 1
|
67
|
-
else
|
68
|
-
remaining << pathname
|
69
|
-
end
|
39
|
+
@option_output = options.delete("output")
|
40
|
+
if !@option_output && @option_concern
|
41
|
+
@option_output = "app/models/#{ACTR::singular_name @option_concern}"
|
70
42
|
end
|
71
|
-
|
72
|
-
|
43
|
+
@option_output = nil if @option_output == "-" # dash for stdout
|
44
|
+
|
45
|
+
@option_validations = options.include?('validations') ? options.delete("validations") : true
|
73
46
|
end
|
74
47
|
|
75
|
-
def
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
82
|
-
return false # File exists, but is not generated
|
83
|
-
rescue Errno::ENOENT
|
84
|
-
return nil # File does not exist
|
48
|
+
def generate_files
|
49
|
+
@composition.
|
50
|
+
all_composite.
|
51
|
+
sort_by{|composite| composite.mapping.name}.
|
52
|
+
map{|composite| generate_composite composite}.
|
53
|
+
compact*"\n"
|
85
54
|
end
|
86
55
|
|
87
|
-
def
|
88
|
-
|
89
|
-
out = $stdout
|
90
|
-
if @option_output
|
91
|
-
pathname = (@option_output+'/'+filename).gsub(%r{//+}, '/')
|
92
|
-
@preexisting_files.reject!{|f| f == pathname } # Don't clean up this file
|
93
|
-
if generated_file_exists(pathname) == false
|
94
|
-
warn "not overwriting non-generated file #{pathname}"
|
95
|
-
@ok = false
|
96
|
-
return nil
|
97
|
-
end
|
98
|
-
out = File.open(pathname, 'w')
|
99
|
-
end
|
100
|
-
out
|
56
|
+
def extant_files
|
57
|
+
Dir[@option_output+'/*.rb'] if @option_output
|
101
58
|
end
|
102
59
|
|
103
60
|
def generate_composite composite
|
@@ -109,9 +66,11 @@ module ActiveFacts
|
|
109
66
|
return model unless @option_output
|
110
67
|
|
111
68
|
filename = composite.rails.singular_name+'.rb'
|
112
|
-
out = create_if_ok(filename)
|
69
|
+
out = create_if_ok(@option_output, filename)
|
113
70
|
return nil unless out
|
114
|
-
out.puts "#{HEADER}\n
|
71
|
+
out.puts "#{HEADER}\n" +
|
72
|
+
"\# #{([File.basename($0)]+ARGV)*' '}\n\n" +
|
73
|
+
model
|
115
74
|
ensure
|
116
75
|
out.close if out
|
117
76
|
nil
|