activefacts-compositions 1.9.22 → 1.9.23
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 +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
|