Skip to content

Commit 83cc7a7

Browse files
committed
--trace option to help debug "Unable to annotate" errors
1 parent 3e89448 commit 83cc7a7

File tree

7 files changed

+110
-37
lines changed

7 files changed

+110
-37
lines changed

History.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
* Add --format=markdown option
6262
* "Table name" annotation (if table name is different from model name)
6363
* "Human name" annotation (enabling translation to non-English locales)
64+
* --trace option to help debug "Unable to annotate" errors
6465

6566
== 2.4.2 2009-11-21
6667

README.rdoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ anywhere in the file:
101101

102102
== OPTIONS
103103

104-
Usage: annotate_models [options] [model_file]*
104+
Usage: annotate [options] [model_file]*
105105
-d, --delete Remove annotations from all model files
106106
-p, --position [before|after] Place the annotations at the top (before) or the bottom (after) of the model file
107107
-r, --routes Annotate routes.rb with the output of 'rake routes'
@@ -117,6 +117,7 @@ anywhere in the file:
117117
-f [bare|rdoc|markdown], Render Schema Infomation as plain/RDoc/Markdown
118118
--format
119119
--force Force new annotations even if there are no changes.
120+
--trace If unable to annotate a file, print the full stack trace, not just the exception message.
120121

121122

122123
== SORTING

Rakefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ task :default => :spec
4444
require "rspec/core/rake_task" # RSpec 2.0
4545
RSpec::Core::RakeTask.new(:spec) do |t|
4646
t.pattern = ['spec/*_spec.rb', 'spec/**/*_spec.rb']
47+
t.rspec_opts = ['--backtrace', '--format d']
4748
end
4849

4950
require 'rdoc/task'

bin/annotate

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ end
1313
task = :annotate_models
1414

1515
OptionParser.new do |opts|
16-
opts.banner = "Usage: annotate_models [options] [model_file]*"
16+
opts.banner = "Usage: annotate [options] [model_file]*"
1717

1818
opts.on('-d', '--delete',
1919
"Remove annotations from all model files") do
@@ -87,6 +87,11 @@ OptionParser.new do |opts|
8787
ENV['force'] = 'yes'
8888
end
8989

90+
opts.on('--trace', 'If unable to annotate a file, print the full stack trace, not just the exception message.') do |value|
91+
ENV['trace'] = 'yes'
92+
end
93+
94+
9095
end.parse!
9196

9297
ENV['is_cli'] = '1'

lib/annotate/annotate_models.rb

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -344,38 +344,35 @@ def do_annotations(options={})
344344
end
345345
end
346346

347-
if options[:model_dir]
348-
self.model_dir = options[:model_dir]
349-
end
347+
self.model_dir = options[:model_dir] if options[:model_dir]
350348

351349
annotated = []
352350
get_model_files(options).each do |file|
353-
begin
354-
klass = get_model_class(file)
355-
if klass && klass < ActiveRecord::Base && !klass.abstract_class?
356-
if annotate(klass, file, header, options)
357-
annotated << klass
358-
end
359-
end
360-
rescue Exception => e
361-
# todo: check if all backtrace lines are in "gems" -- if so, it's an annotate bug, so print the whole stack trace.
362-
puts "Unable to annotate #{file}: #{e.message} (#{e.backtrace.first})"
363-
# todo: save this backtrace somewhere nice
364-
# puts "\t" + e.backtrace.join("\n\t")
365-
end
351+
annotate_model_file(annotated, file, header, options)
366352
end
367353
if annotated.empty?
368354
puts "Nothing annotated."
369355
else
370356
puts "Annotated (#{annotated.length}): #{annotated.join(', ')}"
371357
end
372358
end
373-
374-
def remove_annotations(options={})
375-
if options[:model_dir]
376-
puts "removing"
377-
self.model_dir = options[:model_dir]
359+
360+
def annotate_model_file(annotated, file, header, options)
361+
begin
362+
klass = get_model_class(file)
363+
if klass && klass < ActiveRecord::Base && !klass.abstract_class?
364+
if annotate(klass, file, header, options)
365+
annotated << klass
366+
end
367+
end
368+
rescue Exception => e
369+
puts "Unable to annotate #{file}: #{e.message}"
370+
puts "\t" + e.backtrace.join("\n\t") if options[:trace]
378371
end
372+
end
373+
374+
def remove_annotations(options={})
375+
self.model_dir = options[:model_dir] if options[:model_dir]
379376
deannotated = []
380377
get_model_files(options).each do |file|
381378
begin
@@ -406,7 +403,8 @@ def remove_annotations(options={})
406403

407404
end
408405
rescue Exception => e
409-
puts "Unable to annotate #{file}: #{e.message}"
406+
puts "Unable to deannotate #{file}: #{e.message}"
407+
puts "\t" + e.backtrace.join("\n\t") if options[:trace]
410408
end
411409
end
412410
puts "Removed annotation from: #{deannotated.join(', ')}"

lib/tasks/annotate_models.rake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ task :annotate_models => :environment do
2828
options[:format_markdown] = ENV['format_markdown'] =~ true_re
2929
options[:sort] = ENV['sort'] =~ true_re
3030
options[:force] = ENV['force'] =~ true_re
31+
options[:trace] = ENV['trace'] =~ true_re
3132
AnnotateModels.do_annotations(options)
3233
end
3334

spec/annotate/annotate_models_spec.rb

Lines changed: 79 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,6 @@ class FooWithKnownMacro < ActiveRecord::Base
223223
check_class_name 'foo_with_known_macro.rb', 'FooWithKnownMacro'
224224
end.should == ""
225225
end
226-
227226
end
228227

229228
describe "#remove_annotation_of_file" do
@@ -295,43 +294,110 @@ class Foo < ActiveRecord::Base
295294

296295
describe "annotating a file" do
297296
before do
298-
@file_name = File.join(Dir.mktmpdir('annotate_models'), "user.rb")
299-
@file_content = <<-EOS
297+
@model_dir = Dir.mktmpdir('annotate_models')
298+
write_model "user.rb", <<-EOS
300299
class User < ActiveRecord::Base
301300
end
302301
EOS
303-
File.open(@file_name, "wb") { |f| f.write @file_content }
302+
304303
@klass = mock_class(:users, :id, [
305304
mock_column(:id, :integer),
306305
mock_column(:name, :string, :limit => 50)
307306
])
308307
@schema_info = AnnotateModels.get_schema_info(@klass, "== Schema Info")
309308
end
310309

310+
def write_model file_name, file_content
311+
@model_file_name = File.join(@model_dir, file_name)
312+
@file_content = file_content
313+
File.open(@model_file_name, "wb") { |f| f.write @file_content }
314+
end
315+
316+
def annotate_one_file options = {}
317+
AnnotateModels.annotate_one_file(@model_file_name, @schema_info, options)
318+
end
319+
311320
it "should annotate the file before the model if position == 'before'" do
312-
AnnotateModels.annotate_one_file(@file_name, @schema_info, :position => "before")
313-
File.read(@file_name).should == "#{@schema_info}#{@file_content}"
321+
annotate_one_file :position => "before"
322+
File.read(@model_file_name).should == "#{@schema_info}#{@file_content}"
314323
end
315324

316325
it "should annotate before if given :position => :before" do
317-
AnnotateModels.annotate_one_file(@file_name, @schema_info, :position => :before)
318-
File.read(@file_name).should == "#{@schema_info}#{@file_content}"
326+
annotate_one_file :position => :before
327+
File.read(@model_file_name).should == "#{@schema_info}#{@file_content}"
319328
end
320329

321330
it "should annotate before if given :position => :after" do
322-
AnnotateModels.annotate_one_file(@file_name, @schema_info, :position => :after)
323-
File.read(@file_name).should == "#{@file_content}\n#{@schema_info}"
331+
annotate_one_file :position => :after
332+
File.read(@model_file_name).should == "#{@file_content}\n#{@schema_info}"
324333
end
325334

326335
it "should update annotate position" do
327-
AnnotateModels.annotate_one_file(@file_name, @schema_info, :position => :before)
336+
annotate_one_file :position => :before
328337

329338
another_schema_info = AnnotateModels.get_schema_info(mock_class(:users, :id, [mock_column(:id, :integer),]),
330339
"== Schema Info")
331340

332-
AnnotateModels.annotate_one_file(@file_name, another_schema_info, :position => :after)
341+
@schema_info = another_schema_info
342+
annotate_one_file :position => :after
343+
344+
File.read(@model_file_name).should == "#{@file_content}\n#{another_schema_info}"
345+
end
333346

334-
File.read(@file_name).should == "#{@file_content}\n#{another_schema_info}"
347+
describe "if a file can't be annotated" do
348+
before do
349+
write_model('user.rb', <<-EOS)
350+
class User < ActiveRecord::Base
351+
raise "oops"
352+
end
353+
EOS
354+
end
355+
356+
it "displays an error message" do
357+
capturing(:stdout) {
358+
AnnotateModels.do_annotations :model_dir => @model_dir, :is_rake => true
359+
}.should include("Unable to annotate user.rb: oops")
360+
end
361+
362+
it "displays the full stack trace with --trace" do
363+
capturing(:stdout) {
364+
AnnotateModels.do_annotations :model_dir => @model_dir, :trace => true, :is_rake => true
365+
}.should include("/spec/annotate/annotate_models_spec.rb:")
366+
end
367+
368+
it "omits the full stack trace without --trace" do
369+
capturing(:stdout) {
370+
AnnotateModels.do_annotations :model_dir => @model_dir, :trace => false, :is_rake => true
371+
}.should_not include("/spec/annotate/annotate_models_spec.rb:")
372+
end
373+
end
374+
375+
describe "if a file can't be deannotated" do
376+
before do
377+
write_model('user.rb', <<-EOS)
378+
class User < ActiveRecord::Base
379+
raise "oops"
380+
end
381+
EOS
382+
end
383+
384+
it "displays an error message" do
385+
capturing(:stdout) {
386+
AnnotateModels.remove_annotations :model_dir => @model_dir, :is_rake => true
387+
}.should include("Unable to deannotate user.rb: oops")
388+
end
389+
390+
it "displays the full stack trace" do
391+
capturing(:stdout) {
392+
AnnotateModels.remove_annotations :model_dir => @model_dir, :trace => true, :is_rake => true
393+
}.should include("/user.rb:2:in `<class:User>'")
394+
end
395+
396+
it "omits the full stack trace without --trace" do
397+
capturing(:stdout) {
398+
AnnotateModels.remove_annotations :model_dir => @model_dir, :trace => false, :is_rake => true
399+
}.should_not include("/user.rb:2:in `<class:User>'")
400+
end
335401
end
336402
end
337403
end

0 commit comments

Comments
 (0)