5
6
7
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
|
# File 'lib/stepford/factory_girl_generator.rb', line 5
def self.generate_factories(options={})
factories = {}
expected = {}
included_models = options[:models] ? options[:models].split(',').collect{|s|s.strip}.compact : nil
Dir[File.join('app','models','*.rb').to_s].each do |filename|
model_name = File.basename(filename).sub(/.rb$/, '')
next if included_models && !included_models.include?(model_name)
load File.join('app','models',"#{model_name}.rb")
model_class = model_name.camelize.constantize
next unless model_class.ancestors.include?(ActiveRecord::Base)
factory = (factories[model_name.to_sym] ||= [])
excluded_attributes = Array.wrap(model_class.primary_key).collect{|pk|pk.to_sym} + [:updated_at, :created_at, :object_id]
model_class.reflections.collect {|association_name, reflection|
(expected[reflection.class_name.underscore.to_sym] ||= []) << model_name
excluded_attributes << reflection.foreign_key.to_sym if reflection.foreign_key
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 == reflection.foreign_key.to_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}
model_class.columns.sort_by {|c|[c.name]}.each {|c|
if !excluded_attributes.include?(c.name.to_sym) && !(c.name.downcase.end_with?('_id') && options[:exclude_all_ids]) && (options[:attributes] || !c.null)
factory << "#{is_reserved?(c.name) ? 'self.' : ''}#{c.name} #{Stepford::Common.value_for(c)}"
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|
unless factories[factory_name.to_sym]
puts "#{File.join('app','models',"#{factory_name}.rb")} missing. Model(s) with associations to it: #{expected[factory_name].sort.join(', ')}"
expected[factory_name].each do |model_name|
(model_to_fixes_required[model_name.to_sym] ||= []) << factory_name.to_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|
factory = factories[factory_name]
write_factory(factory_name, 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|
factory = factories[factory_name]
File.open(File.join(path,"#{factory_name}.rb"), "w") do |f|
(f, options)
write_factory(factory_name, factory, f)
(f)
end
end
end
return true
end
|