8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
# File 'lib/stepford/factory_girl/generator.rb', line 8
def self.generate_factories(options={})
factories = {}
expected = {}
included_model_syms = options[:models] ? options[:models].split(',').collect{|s|s.strip.to_sym}.compact : nil
puts "Rails.root=#{Rails.root}"
Dir[Rails.root.join('app','models','*.rb').to_s].each do |filename|
model_name = File.basename(filename).sub(/.rb$/, '')
model_name_sym = model_name.to_sym
next if included_model_syms && !included_model_syms.include?(model_name_sym)
load filename
begin
model_class = model_name.camelize.constantize
rescue => e
puts "Problem in #{model_name.camelize}"
raise e
end
next unless model_class.ancestors.include?(ActiveRecord::Base)
factory = (factories[model_name_sym] ||= [])
pkey_syms = Array.wrap(model_class.primary_key).collect{|pk|pk.to_sym}
excluded_attribute_syms = [:updated_at, :created_at, :object_id]
excluded_attribute_syms_and_pkeys = pkey_syms + [:updated_at, :created_at, :object_id]
model_class.reflections.collect {|association_name, reflection|
begin
reflection.class_name
rescue
puts "#{model_class.name}.#{association_name} failed when attempting to call reflection's class_name method, so skipped association"
next
end
(expected[reflection.class_name.underscore.to_sym] ||= []) << model_name_sym
fkey_sym = reflection.foreign_key.try(:to_sym)
excluded_attribute_syms_and_pkeys << fkey_sym if reflection.foreign_key && !(excluded_attribute_syms_and_pkeys.include?(fkey_sym))
assc_sym = reflection.name.to_sym
clas_sym = reflection.class_name.underscore.to_sym
has_presence_validator = model_class.validators_on(assc_sym).collect{|v|v.class}.include?(ActiveModel::Validations::PresenceValidator)
required = reflection.foreign_key ? (has_presence_validator || model_class.columns.any?{|c| !c.null && c.name.to_sym == fkey_sym}) : false
should_be_trait = !(options[:associations] || (options[:include_required_associations] && required)) && options[:association_traits]
if options[:associations] || (options[:include_required_associations] && required) || should_be_trait
if reflection.macro == :has_many
"#{should_be_trait ? "trait #{"with_#{assc_sym}".to_sym.inspect} do; " : ''}#{should_be_trait || has_presence_validator ? '' : '#'}after(:create) do |user, evaluator|; FactoryGirl.create_list #{clas_sym.inspect}, 2; end#{should_be_trait ? '; end' : ''}#{should_be_trait ? '' : ' # commented to avoid circular reference'}"
elsif assc_sym != clas_sym
"#{should_be_trait ? "trait #{"with_#{assc_sym}".to_sym.inspect} do; " : ''}#{should_be_trait || reflection.macro == :belongs_to || has_presence_validator ? '' : '#'}association #{assc_sym.inspect}#{assc_sym != clas_sym ? ", factory: #{clas_sym.inspect}" : ''}#{should_be_trait ? '; end' : ''}#{should_be_trait || reflection.macro == :belongs_to ? '' : ' # commented to avoid circular reference'}"
else
"#{should_be_trait ? "trait #{"with_#{assc_sym}".to_sym.inspect} do; " : ''}#{should_be_trait || reflection.macro == :belongs_to || has_presence_validator ? '' : '#'}#{is_reserved?(assc_sym) ? 'self.' : ''}#{assc_sym}#{should_be_trait ? '; end' : ''}#{should_be_trait || reflection.macro == :belongs_to ? '' : ' # commented to avoid circular reference'}"
end
else
nil
end
}.compact.sort.each {|l|factory << l}
sequenceless_table = false
begin
sequenceless_table = true unless m.sequence_name
rescue => e
sequenceless_table = true
end
model_column_name_sym_to_column_representation = {}
model_class.columns.each {|c|model_column_name_sym_to_column_representation[c.name.to_sym] = ::Stepford::ColumnRepresentation.new(c)}
::Stepford::FactoryGirl.column_overrides_tree[model_name_sym].each do |column_override_attr_sym, column_override_options|
(model_column_name_sym_to_column_representation[column_override_attr_sym] ||= ::Stepford::ColumnRepresentation.new(column_override_attr_sym)).merge_options(column_override_options)
end if ::Stepford::FactoryGirl.column_overrides_tree && ::Stepford::FactoryGirl.column_overrides_tree[model_name_sym]
model_column_name_sym_to_column_representation.values {|c|[c.name]}.each {|c|
if sequenceless_table && pkey_syms.include?(c.name.to_sym)
factory << ::Stepford::Common.sequence_for(c)
elsif !excluded_attribute_syms_and_pkeys.include?(c.name.to_sym) && !(c.name.to_s.downcase.end_with?('_id') && options[:exclude_all_ids]) && (options[:attributes] || !c.null)
has_uniqueness_validator = model_class.validators_on(c.name.to_sym).collect{|v|v.class}.include?(ActiveRecord::Validations::UniquenessValidator)
if has_uniqueness_validator
factory << ::Stepford::Common.sequence_for(c)
else
factory << "#{is_reserved?(c.name) ? 'self.' : ''}#{c.name} #{Stepford::Common.value_for(c)}"
end
elsif options[:attribute_traits]
if c.type == :boolean
factory << "trait #{c.name.underscore.to_sym.inspect} do; #{is_reserved?(c.name) ? 'self.' : ''}#{c.name} true; end"
factory << "trait #{"not_#{c.name.underscore}".to_sym.inspect} do; #{is_reserved?(c.name) ? 'self.' : ''}#{c.name} false; end"
else
factory << "trait #{"with_#{c.name.underscore}".to_sym.inspect} do; #{is_reserved?(c.name) ? 'self.' : ''}#{c.name} #{Stepford::Common.value_for(c)}; end"
end
end
}
end
if options[:associations] || options[:validate_associations]
failed = false
model_to_fixes_required = {}
expected.keys.sort.each do |factory_name_sym|
unless factories[factory_name_sym]
puts "#{Rails.root.join('app','models',"#{factory_name_sym}.rb")} missing. Model(s) with associations to it: #{expected[factory_name_sym].sort.join(', ')}"
expected[factory_name_sym].each do |model_name|
(model_to_fixes_required[model_name_sym] ||= []) << factory_name_sym
end
failed = true
end
end
model_to_fixes_required.keys.each do |model_to_fix|
puts ""
puts "In #{model_to_fix}:"
model_to_fixes_required[model_to_fix].each do |fix|
puts "- comment/remove/fix broken association to #{fix}"
end
end
return false if failed
end
path = get_factories_rb_pathname(options)
if path.end_with?('.rb')
dirpath = File.dirname(path)
unless File.directory?(dirpath)
puts "Please create this directory first: #{dirpath}"
return false
end
File.open(path, "w") do |f|
(f, options)
factories.keys.sort.each do |factory_name_sym|
factory = factories[factory_name_sym]
write_factory(factory_name_sym, factory, f)
end
(f)
end
else
unless File.directory?(path)
puts "Please create this directory first: #{path}"
return false
end
factories.keys.sort.each do |factory_name_sym|
factory = factories[factory_name_sym]
File.open(File.join(path,"#{factory_name_sym}.rb"), "w") do |f|
(f, options)
write_factory(factory_name_sym, factory, f)
(f)
end
end
end
return true
end
|