Commit 83cc7a7b by Alex Chaffee

--trace option to help debug "Unable to annotate" errors

parent 3e894485
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
* Add --format=markdown option * Add --format=markdown option
* "Table name" annotation (if table name is different from model name) * "Table name" annotation (if table name is different from model name)
* "Human name" annotation (enabling translation to non-English locales) * "Human name" annotation (enabling translation to non-English locales)
* --trace option to help debug "Unable to annotate" errors
== 2.4.2 2009-11-21 == 2.4.2 2009-11-21
......
...@@ -101,7 +101,7 @@ anywhere in the file: ...@@ -101,7 +101,7 @@ anywhere in the file:
== OPTIONS == OPTIONS
Usage: annotate_models [options] [model_file]* Usage: annotate [options] [model_file]*
-d, --delete Remove annotations from all model files -d, --delete Remove annotations from all model files
-p, --position [before|after] Place the annotations at the top (before) or the bottom (after) of the model file -p, --position [before|after] Place the annotations at the top (before) or the bottom (after) of the model file
-r, --routes Annotate routes.rb with the output of 'rake routes' -r, --routes Annotate routes.rb with the output of 'rake routes'
...@@ -117,6 +117,7 @@ anywhere in the file: ...@@ -117,6 +117,7 @@ anywhere in the file:
-f [bare|rdoc|markdown], Render Schema Infomation as plain/RDoc/Markdown -f [bare|rdoc|markdown], Render Schema Infomation as plain/RDoc/Markdown
--format --format
--force Force new annotations even if there are no changes. --force Force new annotations even if there are no changes.
--trace If unable to annotate a file, print the full stack trace, not just the exception message.
== SORTING == SORTING
......
...@@ -44,6 +44,7 @@ task :default => :spec ...@@ -44,6 +44,7 @@ task :default => :spec
require "rspec/core/rake_task" # RSpec 2.0 require "rspec/core/rake_task" # RSpec 2.0
RSpec::Core::RakeTask.new(:spec) do |t| RSpec::Core::RakeTask.new(:spec) do |t|
t.pattern = ['spec/*_spec.rb', 'spec/**/*_spec.rb'] t.pattern = ['spec/*_spec.rb', 'spec/**/*_spec.rb']
t.rspec_opts = ['--backtrace', '--format d']
end end
require 'rdoc/task' require 'rdoc/task'
......
...@@ -13,7 +13,7 @@ end ...@@ -13,7 +13,7 @@ end
task = :annotate_models task = :annotate_models
OptionParser.new do |opts| OptionParser.new do |opts|
opts.banner = "Usage: annotate_models [options] [model_file]*" opts.banner = "Usage: annotate [options] [model_file]*"
opts.on('-d', '--delete', opts.on('-d', '--delete',
"Remove annotations from all model files") do "Remove annotations from all model files") do
...@@ -87,6 +87,11 @@ OptionParser.new do |opts| ...@@ -87,6 +87,11 @@ OptionParser.new do |opts|
ENV['force'] = 'yes' ENV['force'] = 'yes'
end end
opts.on('--trace', 'If unable to annotate a file, print the full stack trace, not just the exception message.') do |value|
ENV['trace'] = 'yes'
end
end.parse! end.parse!
ENV['is_cli'] = '1' ENV['is_cli'] = '1'
......
...@@ -344,25 +344,11 @@ module AnnotateModels ...@@ -344,25 +344,11 @@ module AnnotateModels
end end
end end
if options[:model_dir] self.model_dir = options[:model_dir] if options[:model_dir]
self.model_dir = options[:model_dir]
end
annotated = [] annotated = []
get_model_files(options).each do |file| get_model_files(options).each do |file|
begin annotate_model_file(annotated, file, header, options)
klass = get_model_class(file)
if klass && klass < ActiveRecord::Base && !klass.abstract_class?
if annotate(klass, file, header, options)
annotated << klass
end
end
rescue Exception => e
# todo: check if all backtrace lines are in "gems" -- if so, it's an annotate bug, so print the whole stack trace.
puts "Unable to annotate #{file}: #{e.message} (#{e.backtrace.first})"
# todo: save this backtrace somewhere nice
# puts "\t" + e.backtrace.join("\n\t")
end
end end
if annotated.empty? if annotated.empty?
puts "Nothing annotated." puts "Nothing annotated."
...@@ -370,12 +356,23 @@ module AnnotateModels ...@@ -370,12 +356,23 @@ module AnnotateModels
puts "Annotated (#{annotated.length}): #{annotated.join(', ')}" puts "Annotated (#{annotated.length}): #{annotated.join(', ')}"
end end
end end
def remove_annotations(options={}) def annotate_model_file(annotated, file, header, options)
if options[:model_dir] begin
puts "removing" klass = get_model_class(file)
self.model_dir = options[:model_dir] if klass && klass < ActiveRecord::Base && !klass.abstract_class?
if annotate(klass, file, header, options)
annotated << klass
end
end
rescue Exception => e
puts "Unable to annotate #{file}: #{e.message}"
puts "\t" + e.backtrace.join("\n\t") if options[:trace]
end end
end
def remove_annotations(options={})
self.model_dir = options[:model_dir] if options[:model_dir]
deannotated = [] deannotated = []
get_model_files(options).each do |file| get_model_files(options).each do |file|
begin begin
...@@ -406,7 +403,8 @@ module AnnotateModels ...@@ -406,7 +403,8 @@ module AnnotateModels
end end
rescue Exception => e rescue Exception => e
puts "Unable to annotate #{file}: #{e.message}" puts "Unable to deannotate #{file}: #{e.message}"
puts "\t" + e.backtrace.join("\n\t") if options[:trace]
end end
end end
puts "Removed annotation from: #{deannotated.join(', ')}" puts "Removed annotation from: #{deannotated.join(', ')}"
......
...@@ -28,6 +28,7 @@ task :annotate_models => :environment do ...@@ -28,6 +28,7 @@ task :annotate_models => :environment do
options[:format_markdown] = ENV['format_markdown'] =~ true_re options[:format_markdown] = ENV['format_markdown'] =~ true_re
options[:sort] = ENV['sort'] =~ true_re options[:sort] = ENV['sort'] =~ true_re
options[:force] = ENV['force'] =~ true_re options[:force] = ENV['force'] =~ true_re
options[:trace] = ENV['trace'] =~ true_re
AnnotateModels.do_annotations(options) AnnotateModels.do_annotations(options)
end end
......
...@@ -223,7 +223,6 @@ EOS ...@@ -223,7 +223,6 @@ EOS
check_class_name 'foo_with_known_macro.rb', 'FooWithKnownMacro' check_class_name 'foo_with_known_macro.rb', 'FooWithKnownMacro'
end.should == "" end.should == ""
end end
end end
describe "#remove_annotation_of_file" do describe "#remove_annotation_of_file" do
...@@ -295,12 +294,12 @@ end ...@@ -295,12 +294,12 @@ end
describe "annotating a file" do describe "annotating a file" do
before do before do
@file_name = File.join(Dir.mktmpdir('annotate_models'), "user.rb") @model_dir = Dir.mktmpdir('annotate_models')
@file_content = <<-EOS write_model "user.rb", <<-EOS
class User < ActiveRecord::Base class User < ActiveRecord::Base
end end
EOS EOS
File.open(@file_name, "wb") { |f| f.write @file_content }
@klass = mock_class(:users, :id, [ @klass = mock_class(:users, :id, [
mock_column(:id, :integer), mock_column(:id, :integer),
mock_column(:name, :string, :limit => 50) mock_column(:name, :string, :limit => 50)
...@@ -308,30 +307,97 @@ end ...@@ -308,30 +307,97 @@ end
@schema_info = AnnotateModels.get_schema_info(@klass, "== Schema Info") @schema_info = AnnotateModels.get_schema_info(@klass, "== Schema Info")
end end
def write_model file_name, file_content
@model_file_name = File.join(@model_dir, file_name)
@file_content = file_content
File.open(@model_file_name, "wb") { |f| f.write @file_content }
end
def annotate_one_file options = {}
AnnotateModels.annotate_one_file(@model_file_name, @schema_info, options)
end
it "should annotate the file before the model if position == 'before'" do it "should annotate the file before the model if position == 'before'" do
AnnotateModels.annotate_one_file(@file_name, @schema_info, :position => "before") annotate_one_file :position => "before"
File.read(@file_name).should == "#{@schema_info}#{@file_content}" File.read(@model_file_name).should == "#{@schema_info}#{@file_content}"
end end
it "should annotate before if given :position => :before" do it "should annotate before if given :position => :before" do
AnnotateModels.annotate_one_file(@file_name, @schema_info, :position => :before) annotate_one_file :position => :before
File.read(@file_name).should == "#{@schema_info}#{@file_content}" File.read(@model_file_name).should == "#{@schema_info}#{@file_content}"
end end
it "should annotate before if given :position => :after" do it "should annotate before if given :position => :after" do
AnnotateModels.annotate_one_file(@file_name, @schema_info, :position => :after) annotate_one_file :position => :after
File.read(@file_name).should == "#{@file_content}\n#{@schema_info}" File.read(@model_file_name).should == "#{@file_content}\n#{@schema_info}"
end end
it "should update annotate position" do it "should update annotate position" do
AnnotateModels.annotate_one_file(@file_name, @schema_info, :position => :before) annotate_one_file :position => :before
another_schema_info = AnnotateModels.get_schema_info(mock_class(:users, :id, [mock_column(:id, :integer),]), another_schema_info = AnnotateModels.get_schema_info(mock_class(:users, :id, [mock_column(:id, :integer),]),
"== Schema Info") "== Schema Info")
AnnotateModels.annotate_one_file(@file_name, another_schema_info, :position => :after) @schema_info = another_schema_info
annotate_one_file :position => :after
File.read(@model_file_name).should == "#{@file_content}\n#{another_schema_info}"
end
File.read(@file_name).should == "#{@file_content}\n#{another_schema_info}" describe "if a file can't be annotated" do
before do
write_model('user.rb', <<-EOS)
class User < ActiveRecord::Base
raise "oops"
end
EOS
end
it "displays an error message" do
capturing(:stdout) {
AnnotateModels.do_annotations :model_dir => @model_dir, :is_rake => true
}.should include("Unable to annotate user.rb: oops")
end
it "displays the full stack trace with --trace" do
capturing(:stdout) {
AnnotateModels.do_annotations :model_dir => @model_dir, :trace => true, :is_rake => true
}.should include("/spec/annotate/annotate_models_spec.rb:")
end
it "omits the full stack trace without --trace" do
capturing(:stdout) {
AnnotateModels.do_annotations :model_dir => @model_dir, :trace => false, :is_rake => true
}.should_not include("/spec/annotate/annotate_models_spec.rb:")
end
end
describe "if a file can't be deannotated" do
before do
write_model('user.rb', <<-EOS)
class User < ActiveRecord::Base
raise "oops"
end
EOS
end
it "displays an error message" do
capturing(:stdout) {
AnnotateModels.remove_annotations :model_dir => @model_dir, :is_rake => true
}.should include("Unable to deannotate user.rb: oops")
end
it "displays the full stack trace" do
capturing(:stdout) {
AnnotateModels.remove_annotations :model_dir => @model_dir, :trace => true, :is_rake => true
}.should include("/user.rb:2:in `<class:User>'")
end
it "omits the full stack trace without --trace" do
capturing(:stdout) {
AnnotateModels.remove_annotations :model_dir => @model_dir, :trace => false, :is_rake => true
}.should_not include("/user.rb:2:in `<class:User>'")
end
end end
end end
end end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment