Class: CodeBase

Inherits:
Object show all
Includes:
NoDB
Defined in:
app/models/code.rb

Constant Summary collapse

AFFECTS_EVERYTHING =

[]=

["db/schema.rb","test/test_helper.rb",'app/models/global.rb','app/models/generic_table.rb']
AFFECTS_CONTROLLERS =
Dir['app/views/shared/*']
@@TABLE_FINDER_REGEXPS =
name, example_pathname, Dir_glob, plural,test_type

plural can be true false or nil (not model specific)

[
{:name => :models, :example_pathname => 'app/models/global.rb', :Dir_glob =>  'app/models/([a-zA-Z0-9_]*)[.]rb', :plural => false, :test_type => :both},
{:name => :testing, :example_pathname => 'test/test_helper.rb', :Dir_glob =>  'test/[a-zA-Z0-9_]*[.]r[a-z]*', :plural => nil, :test_type => :both},
{:name => :unit_tests, :example_pathname => 'test/unit/global_test.rb', :Dir_glob =>  'test/unit/([a-zA-Z0-9_]*)_test[.]rb', :plural => false, :test_type => :unit},
{:name => :functional_tests, :example_pathname => 'test/functional/stream_patterns_controller_test.rb', :Dir_glob =>  'test/functional/([a-zA-Z0-9_]*)_controller_test[.]rb', :plural => true, :test_type => :controller},
{:name => :unit_test_logs, :example_pathname => 'log/unit/generic_table_test.log', :Dir_glob =>  'log/unit/([a-zA-Z0-9_]*)([.a-zA-Z0-9_]*)_test[.]log', :plural => false, :test_type => :unit},
{:name => :functional_test_logs, :example_pathname => 'log/functional/stream_patterns_controller_test.log', :Dir_glob =>  'log/functional/([a-zA-Z0-9_]*)_controller_test[.]log', :plural => true, :test_type => :controller},
{:name => :new_views, :example_pathname => 'app/views/acquisition_stream_specs/new.html.erb', :Dir_glob =>  'app/views/([a-z_]*)/new[.]html[.]erb', :plural => true, :test_type => :controller},
{:name => :edit_views, :example_pathname => 'app/views/acquisition_stream_specs/edit.html.erb', :Dir_glob =>  'app/views/([a-z_]*)/edit[.]html[.]erb', :plural => true, :test_type => :controller},
{:name => :show_views, :example_pathname => 'app/views/acquisition_stream_specs/show.html.erb', :Dir_glob =>  'app/views/([a-z_]*)/show[.]html[.]erb', :plural => true, :test_type => :controller},
{:name => :index_views, :example_pathname => 'app/views/acquisition_stream_specs/index.html.erb', :Dir_glob =>  'app/views/([a-z_]*)/index[.]html[.]erb', :plural => true, :test_type => :controller},
{:name => :shared_partials, :example_pathname => 'app/views/shared/_multi-line.html.erb', :Dir_glob =>  'app/views/shared/_[a-zA-Z0-9_-]*[.]html[.]erb', :plural => nil, :test_type => :controller},
{:name => :form_partials, :example_pathname => 'app/views/stream_patterns/_form.html.erb', :Dir_glob =>  'app/views/([a-z_]*)/_form[.]html[.]erb', :plural => true, :test_type => :controller},
{:name => :show_partials, :example_pathname => 'app/views/stream_patterns/_show_partial.html.erb', :Dir_glob =>  'app/views/([a-z_]*)/_show_partial[.]html[.]erb', :plural => true, :test_type => :controller},
{:name => :index_partials, :example_pathname => 'app/views/stream_patterns/_index_partial.html.erb', :Dir_glob =>  'app/views/([a-z_]*)/_index_partial[.]html[.]erb', :plural => true, :test_type => :controller},
{:name => :controllers, :example_pathname => 'app/controllers/stream_patterns_controller.rb', :Dir_glob =>  'app/controllers/([a-z0-9_]*)_controller[.]rb', :plural => true, :test_type => :controller}
]

Constants included from NoDB

NoDB::DEFAULT_TYPE

Constants included from ColumnGroup::ClassMethods

ColumnGroup::ClassMethods::History_columns

Constants included from GenericGrep::ClassMethods

GenericGrep::ClassMethods::ASSOCIATION_MACRO_LETTERS, GenericGrep::ClassMethods::ASSOCIATION_MACRO_PATTERN

Constants included from GenericTableAssociation::Examples

GenericTableAssociation::Examples::First_stream_method

Instance Attribute Summary

Attributes included from NoDB

#attributes

Class Method Summary collapse

Instance Method Summary collapse

Methods included from NoDB

#[], #clone, #each_pair, #has_key?, #insert_sql, #keys, #table_class, #table_name

Methods included from Generic_Table::ClassMethods

#is_active_record_method?, #model_file_name, #nesting, #one_pass_statistics, #sample, #sample_burst

Methods included from ColumnGroup::ClassMethods

#attribute_ddl, #attribute_rails_type, #attribute_ruby_type, #candidate_logical_keys_from_indexes, #categorical?, #column_symbols, #default_logical_primary_key, #defaulted_primary_logical_key?, #history_type?, #is_logical_primary_key?, #logical_attributes, #logical_primary_key, #logical_primary_key_recursive, #numerical?, #probably_categorical?, #probably_numerical?, #sequential_id?

Methods included from GenericGrep::ClassMethods

#all_associations, #association_grep, #association_grep_pattern, #association_macro_type, #association_type, #belongs_to_association?, #grep_all_associations_command, #grep_command, #has_many_association?, #has_one_association?, #model_grep, #model_grep_command

Methods included from GenericTableHtml::ClassMethods

#column_order, #header_html, #table_html

Methods included from Generic_Table

activeRecordTableNotCreatedYet?, classDefiniton, classReference, class_of_name, eval_constant, is_ActiveRecord_table?, is_generic_table?, is_generic_table_name?, is_table?, rails_MVC_class?, rubyClassName, table_exists?

Methods included from GenericTableAssociation

#associated_foreign_key_records, #associated_to_s, #association_class, #association_has_data, #association_state, #foreign_key_points_to_me?, #foreign_key_to_association, #foreign_key_value, #logical_primary_key_recursive_value, #logical_primary_key_value, #name_to_association

Methods included from GenericTableAssociation::Assertions::ClassMethods

#assert_foreign_keys_not_nil, #assert_invariant, #assert_post_conditions, #assert_pre_conditions

Methods included from GenericTableAssociation::Assertions

#assert_associated_foreign_key, #assert_associated_foreign_key_name, #assert_association, #assert_association_methods, #assert_association_to_many, #assert_association_to_one, #assert_foreign_key_association_names, #assert_foreign_key_name, #assert_foreign_key_not_nil, #assert_foreign_keys_not_nil, #assert_invariant, #assert_post_conditions, #assert_pre_conditions

Methods included from GenericTableHtml

#column_html, #rails_route, #row_html

Constructor Details

#initialize(hash = nil) ⇒ CodeBase

Initializes a spec from a hash


33
34
35
# File 'app/models/code.rb', line 33

def initialize(hash=nil)
	@hash=hash
end

Class Method Details

.allObject

Returns all specs


37
38
39
# File 'app/models/code.rb', line 37

def CodeBase.all
	return @@TABLE_FINDER_REGEXPS.map {|spec| CodeBase.new(spec)}
end

.controller_sources(singular_table) ⇒ Object

unit_sources


88
89
90
91
92
93
94
# File 'app/models/code.rb', line 88

def CodeBase.controller_sources(singular_table)
	plural_table=singular_table.pluralize
	# commn_sources apply to both unit and functional tests.
	common_sources=AFFECTS_EVERYTHING+[model_pathname(singular_table),"test/fixtures/#{plural_table}.yml"]
	sources=common_sources+Dir["app/views/#{plural_table}/*.html.erb"]+AFFECTS_CONTROLLERS
	return ["test/functional/#{plural_table}_controller_test.rb"] +sources+["app/controllers/#{plural_table}_controller.rb","app/helpers/#{plural_table}_helper.rb"]
end

.controller_target(singular_table) ⇒ Object

unit_target


98
99
100
101
# File 'app/models/code.rb', line 98

def CodeBase.controller_target(singular_table)
	plural_table=singular_table.pluralize
	return "log/functional/#{plural_table}_controller_test.log"
end

.find_by_name(spec_name_symbol) ⇒ Object

like ActiveRecord method


109
110
111
112
113
# File 'app/models/code.rb', line 109

def CodeBase.find_by_name(spec_name_symbol)
	index=CodeBase.all.index {|s| s[:name]==spec_name_symbol.to_sym}
	raise "spec_name_symbol=#{spec_name_symbol} not found" if index.nil?
	return CodeBase.all[index]
end

.git_add_successful(not_uptodate_sources) ⇒ Object

gitStatus


178
179
180
181
182
183
# File 'app/models/code.rb', line 178

def CodeBase.git_add_successful(not_uptodate_sources)
	not_uptodate_sources.each do |s|
		sh "git add #{s}"
	end #each
	sh "git-cola"
end

.gitStatus(&process_status) ⇒ Object

not_uptodate_sources


171
172
173
174
175
176
177
# File 'app/models/code.rb', line 171

def CodeBase.gitStatus(&process_status)
	modified_files=`git ls-files --modified`.split("\n") - `git ls-files --deleted`.split("\n")
	return modified_files.map do |pathname| 
#		status,pathname=line.split(" ")
		process_status.call('M',pathname)
	end #each
end

.model_pathname(singular_table) ⇒ Object

test_pathname


78
79
80
# File 'app/models/code.rb', line 78

def CodeBase.model_pathname(singular_table)
	return "app/models/#{singular_table}.rb"
end

.model_spec_symbolsObject

controller_target


102
103
104
# File 'app/models/code.rb', line 102

def CodeBase.model_spec_symbols
	return CodeBase.all.select {|s| s[:test_type]!=:both}.map {|s| s[:name]}
end

.not_uptodate_sources(target, sources) ⇒ Object

determine which pathnames should be staged if test is successful all pathnames newer than previous test log. pathname must also have changed since last staging


159
160
161
162
163
164
165
166
167
168
169
170
# File 'app/models/code.rb', line 159

def CodeBase.not_uptodate_sources(target, sources)
	raise "sources=#{sources.inspect} must be an Array" unless sources.instance_of?(Array)
	puts "sources=#{sources.inspect} must be an Array of Strings(pathnames)"
	puts "sources.size=#{sources.size} "
	puts "sources[0]=#{sources[0].inspect} "
	sources.each do |p|
		puts "p=#{p.inspect} must be a String(pathnames)" unless p.instance_of?(String)
	end #each
	raise "sources=#{sources.inspect} must be an Array of Strings(pathnames)" unless sources.any?{|s| s.instance_of?(String)}
	raise "target=#{target.inspect} must be a String (pathnames)" unless target.instance_of?(String)
	sources.select {|s| !File.exist?(target) ||  File.exist?(s) && !uptodate?(target, [s])}
end

.rails_MVC_classesObject


231
232
233
234
235
236
237
238
239
240
241
242
# File 'app/models/code.rb', line 231

def CodeBase.rails_MVC_classes
#	puts fixture_names.inspect
	@@ALL_VIEW_DIRS.map do |view_dir|
		model_pathnamename=view_dir.sub(%r{^app/views/},'')
		if Generic_Table.is_generic_table_name?(model_pathnamename.singularize) then
			model_pathnamename.classify.constantize
		else
#			puts "File.exists?(\"app/models/#{model_pathnamename}\")=#{File.exists?('app/models/'+model_pathnamename)}"
			nil # discarded by later Array#compact
		end #if
	end.compact #map
end

.spec_symbolsObject

model_spec_symbols


105
106
107
# File 'app/models/code.rb', line 105

def CodeBase.spec_symbols
	return CodeBase.all.map {|s| s[:name]}
end

.test_pathname(singular_table, test_type) ⇒ Object


69
70
71
72
73
74
75
76
77
# File 'app/models/code.rb', line 69

def CodeBase.test_pathname(singular_table, test_type)
	case test_type.to_sym
	when :unit
		return "test/unit/#{singular_table}_test.rb"
	when :controller
		return "test/functional/#{plural_table}_controller_test.rb"
	else raise "Unnown test_type=#{test_type} for singular_table=#{singular_table}"
	end #case
end

.unit_sources(singular_table) ⇒ Object

model_pathname


81
82
83
84
85
86
87
# File 'app/models/code.rb', line 81

def CodeBase.unit_sources(singular_table)
	plural_table=singular_table.pluralize
	# commn_sources apply to both unit and functional tests.
	model_pathname="app/models/#{singular_table}.rb"
	common_sources=AFFECTS_EVERYTHING+[model_pathname,"test/fixtures/#{plural_table}.yml"]
	return ["test/unit/#{singular_table}_test.rb"]+common_sources
end

.unit_target(singular_table) ⇒ Object

controller_sources


95
96
97
# File 'app/models/code.rb', line 95

def CodeBase.unit_target(singular_table)
	return "log/unit/#{singular_table}_test.log"
end

.uptodate?(target, sources) ⇒ Boolean

models

Returns:

  • (Boolean)

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'app/models/code.rb', line 138

def CodeBase.uptodate?(target,sources) 
	raise "sources=#{sources.inspect} must be an Array of Strings(pathnames)" unless sources.instance_of?(Array)
	raise "target=#{target.inspect} must be a String (pathnames)" unless target.instance_of?(String)
	sources.each do |s|
		#~ system ("ls -l #{target}") {|ok, res| } # discard result if pathname doesn't exist
		#~ system "ls -l #{s}"
		if !File.exist?(target) then
			return false
		end #def
		if !File.exist?(s) then
			return false
		end #def
		if File.mtime(target)<File.mtime(s) then
			return false
		end #if
	end #each
	return true
end

.why_not_stage(pathname, singular_table) ⇒ Object

stage target and source pathnames when all tests pass. stage model pathname and .yml pathnames when BOTH unit and controller tests pass


217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'app/models/code.rb', line 217

def CodeBase.why_not_stage(pathname,singular_table)
	match_spec=MatchedPathName.new(pathname)
	if match_spec.nil? then
		singular_table=FILE_MOD_TIMES[FILE_MOD_TIMES.size/2][0] # pick average pathname, not too active, not too abandoned
		puts "#{pathname} don't know when to stage."
	else
		singular_table=MatchedPathName.new(pathname).model_name.singular_model_name
		why_not_stage_helper(pathname,unit_target(singular_table),unit_sources(singular_table),:unit)  if match_spec[:test_type] != :controller
		if File.exists?(controller_target(singular_table)) then
			why_not_stage_helper(pathname,controller_target(singular_table),controller_sources(singular_table),:controller)  if match_spec[:test_type] != :unit
		end #if
	end #if
end

.why_not_stage_helper(pathname, target, sources, test_type) ⇒ Object

stage target and source pathnames when all tests pass. stage model pathname and .yml pathnames when BOTH unit and controller tests pass


187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'app/models/code.rb', line 187

def CodeBase.why_not_stage_helper(pathname,target,sources,test_type)
	if File.exists?(target) then
		#~ puts "Target #{target}  does exist." 
		if TestRun.log_passed?(target) then
			system "git add #{target}"
			if pathname==target then
				return true
			elsif  uptodate?(target,[pathname]) then
				if sources.include?(pathname) then
					system "git add #{pathname}"
					return true
				else
					puts "#{pathname} not a #{test_type} source."
					return false
				end #if
			else
				puts "#{pathname} not up to date." 
			end #if
			return true
		else
			return false
		end #if
	else
		puts "Target #{target} for pathname=#{pathname} does not exist."
		return false
	end #if

end

Instance Method Details

#[]=(name, attribute) ⇒ Object

pathnames


63
64
65
# File 'app/models/code.rb', line 63

def []=(name, attribute)
	self[name]=attribute.class.new(attribute)
end

#modelsObject

for given spec return models


120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'app/models/code.rb', line 120

def models
	if pathnames_with_models? then
		models=pathnames.map do|f|
			model=f[self.regexp,1]
			if model.nil? then
				raise "pathname=#{f} does not match regexp=#{self.regexp}"
			end #if
			if self[:plural] then
				model=model.singularize
			end #if
			model
		end #map
		return Set.new(models)
	else
		return Set[]
	end #if
	
end

#pathname_globObject

Returns a file glob to find pathname, removing parenthesis golbs are defined at www.ruby-doc.org/core-1.9.3/Dir.html#method-c-glob


42
43
44
45
46
# File 'app/models/code.rb', line 42

def pathname_glob
	ret=RegexpTree.new(self[:Dir_glob]).to_pathname_glob
#	ret=self[:Dir_glob].sub(/(\()/,'').sub(/(\))/,'')
	return ret
end

#pathnamesObject

Find array of pathnames that match CodeBase spec


58
59
60
61
62
# File 'app/models/code.rb', line 58

def pathnames
	Dir[pathname_glob].select do |pathname|
		regexp.match(pathname)
	end #select
end

#pathnames_with_models?Boolean

find_by_name

Returns:

  • (Boolean)

114
115
116
117
118
# File 'app/models/code.rb', line 114

def pathnames_with_models?
	pathnames.all? do|f|
		self.regexp.match(f).size>1
	end #select
end

#regexpObject

Returns a Regexp to extract model names from pathname, keeping parenthesis Regexp syntax is defined at www.ruby-doc.org/core-1.9.3/Regexp.html specify as a regexp with added parenthesis for model name (and test) capture globs are less powerful than regexp, so to make them convertable, we specify regexps and convert to globs then match with regexp implementation currently incomplete [a-z]* does not glob any word but any string starting with a letter!


53
54
55
56
# File 'app/models/code.rb', line 53

def regexp
	ret='^'+self[:Dir_glob]+'$'
	return Regexp.new(ret)
end