Commit 6e41ec0a by Jon Frisby

Merge remote-tracking branch 'miyucy/restart'

WARNING: EVIL MERGE. I'm fixing a number of problems with this branch and ommitting one or two things. Conflicts: .gitignore History.txt README.rdoc Rakefile VERSION.yml annotate.gemspec lib/annotate/annotate_models.rb lib/tasks/annotate_models.rake lib/tasks/annotate_routes.rake lib/tasks/migrate.rake spec/annotate/annotate_models_spec.rb spec/spec_helper.rb
parents cc7f3b15 280a9e56
...@@ -3,6 +3,7 @@ source :rubygems ...@@ -3,6 +3,7 @@ source :rubygems
group :development do group :development do
gem 'jeweler' gem 'jeweler'
gem 'rspec' gem 'rspec'
gem 'fakefs', :require => false
end end
gem 'active_support' gem 'activesupport', :require => nil
...@@ -5,6 +5,7 @@ GEM ...@@ -5,6 +5,7 @@ GEM
activesupport (= 3.0.0) activesupport (= 3.0.0)
activesupport (3.0.0) activesupport (3.0.0)
diff-lcs (1.1.3) diff-lcs (1.1.3)
fakefs (0.4.0)
git (1.2.5) git (1.2.5)
jeweler (1.6.4) jeweler (1.6.4)
bundler (~> 1.0) bundler (~> 1.0)
...@@ -25,5 +26,6 @@ PLATFORMS ...@@ -25,5 +26,6 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
active_support active_support
fakefs
jeweler jeweler
rspec rspec
...@@ -24,6 +24,20 @@ ...@@ -24,6 +24,20 @@
* Rename "annotate" bin to "annotate_models" to avoid conflicting with * Rename "annotate" bin to "annotate_models" to avoid conflicting with
ImageMagick. ImageMagick.
== 2.4.2 2009-11-21
* Annotates (spec|test)/factories/<model>_factory.rb files
== 2.4.1 2009-11-20
* Annotates thoughtbot's factory_girl factories (test/factories/<model>_factory.rb)
* Move default annotation position back to top
== 2.4.0 2009-12-13
* Incorporated lots of patches from the Github community, including support for Blueprints fixtures
* Several bug fixes
== 2.1 2009-10-18 == 2.1 2009-10-18
* New options * New options
......
...@@ -8,6 +8,7 @@ Add a comment summarizing the current schema to the top or bottom of each of you ...@@ -8,6 +8,7 @@ Add a comment summarizing the current schema to the top or bottom of each of you
* Object Daddy exemplars * Object Daddy exemplars
* Machinist blueprints * Machinist blueprints
* Fabrication fabricators * Fabrication fabricators
* Thoughtbot's factory_girl factories, i.e. the (spec|test)/factories/<model>_factory.rb files
The schema comment looks like this: The schema comment looks like this:
...@@ -96,7 +97,8 @@ you can use to tailor the output. ...@@ -96,7 +97,8 @@ you can use to tailor the output.
-s, --simple-indexes Concat the column's related indexes in the annotation -s, --simple-indexes Concat the column's related indexes in the annotation
--model-dir dir Annotate model files stored in dir rather than app/models --model-dir dir Annotate model files stored in dir rather than app/models
-R, --require path Additional files to require before loading models -R, --require path Additional files to require before loading models
-e, --exclude [tests,fixtures] Do not annotate fixtures, test files, or both -e [tests,fixtures,factories] Do not annotate fixtures, test files, and/or factories
--exclude
== WARNING == WARNING
...@@ -110,7 +112,7 @@ to an automatically created comment block. ...@@ -110,7 +112,7 @@ to an automatically created comment block.
== LINKS == LINKS
* Factory Girl => http://github.com/thoughtbot/factory_girl (NOT IMPLEMENTED) * Factory Girl => http://github.com/thoughtbot/factory_girl
* Object Daddy => http://github.com/flogic/object_daddy * Object Daddy => http://github.com/flogic/object_daddy
* Machinist => http://github.com/notahat/machinist * Machinist => http://github.com/notahat/machinist
* Fabrication => http://github.com/paulelliott/fabrication * Fabrication => http://github.com/paulelliott/fabrication
...@@ -144,6 +146,7 @@ Modifications by: ...@@ -144,6 +146,7 @@ Modifications by:
- Bob Potter - http://github.com/bpot - Bob Potter - http://github.com/bpot
- Gavin Montague - http://github.com/govan/ - Gavin Montague - http://github.com/govan/
- Alexander Semyonov - http://github.com/rotuka/ - Alexander Semyonov - http://github.com/rotuka/
- Nathan Brazil - http://github.com/bitaxis/
- Ian Duggan http://github.com/ijcd/ - Ian Duggan http://github.com/ijcd/
- Jon Frisby http://github.com/mrjoy/ - Jon Frisby http://github.com/mrjoy/
......
...@@ -32,12 +32,6 @@ RSpec::Core::RakeTask.new(:spec) do |t| ...@@ -32,12 +32,6 @@ RSpec::Core::RakeTask.new(:spec) do |t|
t.pattern = ['spec/*_spec.rb', 'spec/**/*_spec.rb'] t.pattern = ['spec/*_spec.rb', 'spec/**/*_spec.rb']
end end
# FIXME not working yet
RSpec::Core::RakeTask.new(:rcov) do |t|
t.pattern = 'spec/**/*_spec.rb'
t.rcov = true
end
# FIXME warns "already initialized constant Task" # FIXME warns "already initialized constant Task"
# FIXME throws "uninitialized constant RDoc::VISIBILITIES" # FIXME throws "uninitialized constant RDoc::VISIBILITIES"
# require 'rdoc/task' # require 'rdoc/task'
......
--- ---
:major: 2 :major: 2
:minor: 4 :minor: 4
:patch: 1 :patch: 2
:build: 'beta1'
\ No newline at end of file
...@@ -5,13 +5,14 @@ ...@@ -5,13 +5,14 @@
Gem::Specification.new do |s| Gem::Specification.new do |s|
s.name = "annotate" s.name = "annotate"
s.version = "2.4.1.beta1" s.version = "2.4.2"
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version= s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Cuong Tran", "Alex Chaffee", "Marcos Piccinini", "Turadg Aleahmad"] s.authors = ["Cuong Tran", "Alex Chaffee", "Marcos Piccinini", "Turadg Aleahmad"]
s.date = "2012-03-01" s.date = "2012-03-01"
s.description = "When run, inserts table descriptions from db.schema into a comment block of relevant source code." s.description = "When run, inserts table descriptions from db.schema into a comment block of relevant source code."
s.email = ["alex@stinky.com", "ctran@pragmaquest.com", "x@nofxx.com", "turadg@aleahmad.net"] s.email = ["alex@stinky.com", "ctran@pragmaquest.com", "x@nofxx.com", "turadg@aleahmad.net"]
s.executables = ["annotate_models"]
s.extra_rdoc_files = [ s.extra_rdoc_files = [
"README.rdoc" "README.rdoc"
] ]
...@@ -24,6 +25,7 @@ Gem::Specification.new do |s| ...@@ -24,6 +25,7 @@ Gem::Specification.new do |s|
"Rakefile", "Rakefile",
"VERSION.yml", "VERSION.yml",
"annotate.gemspec", "annotate.gemspec",
"bin/annotate_models",
"lib/annotate.rb", "lib/annotate.rb",
"lib/annotate/active_record_patch.rb", "lib/annotate/active_record_patch.rb",
"lib/annotate/annotate_models.rb", "lib/annotate/annotate_models.rb",
......
...@@ -63,6 +63,10 @@ OptionParser.new do |opts| ...@@ -63,6 +63,10 @@ OptionParser.new do |opts|
exclusions.each { |exclusion| ENV["exclude_#{exclusion}"] = "yes" } exclusions.each { |exclusion| ENV["exclude_#{exclusion}"] = "yes" }
end end
opts.on('-f', '--format [bare|rdoc]', ['bare', 'rdoc'], 'rdoc: render Schema Infomation as RDoc') do |fmt|
ENV['format_#{fmt}'] = 'yes'
end
end.parse! end.parse!
if Annotate.load_tasks if Annotate.load_tasks
......
$:.unshift(File.dirname(__FILE__)) unless
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
require 'yaml' require 'yaml'
......
module AnnotateModels module AnnotateModels
class << self
# Annotate Models plugin use this header # Annotate Models plugin use this header
COMPAT_PREFIX = "== Schema Info" COMPAT_PREFIX = "== Schema Info"
PREFIX = "== Schema Information" PREFIX = "== Schema Information"
END_MARK = "== Schema Information End"
FIXTURE_DIRS = ["test/fixtures","spec/fixtures"] PATTERN = /\n?# #{COMPAT_PREFIX}.*?\n(#.*\n)*\n*/
# File.join for windows reverse bar compat? # File.join for windows reverse bar compat?
# I dont use windows, can`t test # I dont use windows, can`t test
UNIT_TEST_DIR = File.join("test", "unit" ) UNIT_TEST_DIR = File.join("test", "unit" )
SPEC_MODEL_DIR = File.join("spec", "models") SPEC_MODEL_DIR = File.join("spec", "models")
# Object Daddy http://github.com/flogic/object_daddy FIXTURE_TEST_DIR = File.join("test", "fixtures")
FIXTURE_SPEC_DIR = File.join("spec", "fixtures")
# Object Daddy http://github.com/flogic/object_daddy/tree/master
EXEMPLARS_TEST_DIR = File.join("test", "exemplars") EXEMPLARS_TEST_DIR = File.join("test", "exemplars")
EXEMPLARS_SPEC_DIR = File.join("spec", "exemplars") EXEMPLARS_SPEC_DIR = File.join("spec", "exemplars")
# Machinist http://github.com/notahat/machinist # Machinist http://github.com/notahat/machinist
BLUEPRINTS_DIR = File.join("test", "blueprints") BLUEPRINTS_TEST_DIR = File.join("test", "blueprints")
# FactoryGirl http://github.com/thoughtbot/factory_girl BLUEPRINTS_SPEC_DIR = File.join("spec", "blueprints")
FACTORIES_TEST_DIR = File.join("test", "factories") # Factory Girl http://github.com/thoughtbot/factory_girl
FACTORIES_SPEC_DIR = File.join("spec", "factories") FACTORY_GIRL_TEST_DIR = File.join("test", "factories")
FACTORY_GIRL_SPEC_DIR = File.join("spec", "factories")
# Fabrication https://github.com/paulelliott/fabrication.git # Fabrication https://github.com/paulelliott/fabrication.git
FABRICATORS_TEST_DIR = File.join("test", "fabricators") FABRICATORS_TEST_DIR = File.join("test", "fabricators")
FABRICATORS_SPEC_DIR = File.join("spec", "fabricators") FABRICATORS_SPEC_DIR = File.join("spec", "fabricators")
# Don't show limit (#) on these column types
# Example: show "integer" instead of "integer(4)"
NO_LIMIT_COL_TYPES = ["integer", "boolean"]
class << self
def model_dir def model_dir
@model_dir || "app/models" @model_dir || "app/models"
end end
...@@ -49,22 +55,26 @@ module AnnotateModels ...@@ -49,22 +55,26 @@ module AnnotateModels
# each column. The line contains the column name, # each column. The line contains the column name,
# the type (and length), and any optional attributes # the type (and length), and any optional attributes
def get_schema_info(klass, header, options = {}) def get_schema_info(klass, header, options = {})
info = "# #{header}\n#\n" info = "# #{header}\n"
info << "# Table name: #{klass.table_name}\n#\n" info<< "#\n"
info<< "# Table name: #{klass.table_name}\n"
info<< "#\n"
max_size = klass.column_names.collect{|name| name.size}.max || 0 max_size = klass.column_names.map{|name| name.size}.max || 0
max_size += 1 max_size += ENV['format_rdoc'] ? 5 : 1
klass.columns.sort_by(&:name).each do |col| klass.columns.sort_by(&:name).each do |col|
attrs = [] attrs = []
attrs << "default(#{quote(col.default)})" unless col.default.nil? attrs << "default(#{quote(col.default)})" unless col.default.nil?
attrs << "not null" unless col.null attrs << "not null" unless col.null
attrs << "primary key" if col.name == klass.primary_key attrs << "primary key" if col.name.to_sym == klass.primary_key.to_sym
col_type = (col.type || col.sql_type).to_s col_type = (col.type || col.sql_type).to_s
if col_type == "decimal" if col_type == "decimal"
col_type << "(#{col.precision}, #{col.scale})" col_type << "(#{col.precision}, #{col.scale})"
else else
col_type << "(#{col.limit})" if col.limit if (col.limit)
col_type << "(#{col.limit})" unless NO_LIMIT_COL_TYPES.include?(col_type)
end
end end
# Check out if we got a geometric column # Check out if we got a geometric column
...@@ -85,15 +95,25 @@ module AnnotateModels ...@@ -85,15 +95,25 @@ module AnnotateModels
end end
end end
if ENV['format_rdoc']
info << sprintf("# %-#{max_size}.#{max_size}s<tt>%s</tt>", "*#{col.name}*::", attrs.unshift(col_type).join(", ")).rstrip + "\n"
else
info << sprintf("# %-#{max_size}.#{max_size}s:%-15.15s %s", col.name, col_type, attrs.join(", ")).rstrip + "\n" info << sprintf("# %-#{max_size}.#{max_size}s:%-15.15s %s", col.name, col_type, attrs.join(", ")).rstrip + "\n"
end end
end
if options[:show_indexes] && klass.table_exists? if options[:show_indexes] && klass.table_exists?
info << get_index_info(klass) info << get_index_info(klass)
end end
if ENV['format_rdoc']
info << "#--\n"
info << "# #{END_MARK}\n"
info << "#++\n\n"
else
info << "#\n\n" info << "#\n\n"
end end
end
def get_index_info(klass) def get_index_info(klass)
index_info = "#\n# Indexes\n#\n" index_info = "#\n# Indexes\n#\n"
...@@ -136,21 +156,18 @@ module AnnotateModels ...@@ -136,21 +156,18 @@ module AnnotateModels
old_columns = old_header && old_header.scan(column_pattern).sort old_columns = old_header && old_header.scan(column_pattern).sort
new_columns = new_header && new_header.scan(column_pattern).sort new_columns = new_header && new_header.scan(column_pattern).sort
encoding = Regexp.new(/(^# encoding:.*\n)|(^# coding:.*\n)|(^# -\*- coding:.*\n)/) encoding = Regexp.new(/(^#\s*encoding:.*\n)|(^# coding:.*\n)|(^# -\*- coding:.*\n)/)
encoding_header = old_content.match(encoding).to_s encoding_header = old_content.match(encoding).to_s
if old_columns == new_columns if old_columns == new_columns
false false
else else
# Replace the old schema info with the new schema info # Strip the old schema info, and insert new schema info.
new_content = old_content.sub(/^# #{COMPAT_PREFIX}.*?\n(#.*\n)*\n*/, info_block)
# But, if there *was* no old schema info, we simply need to insert it
if new_content == old_content
old_content.sub!(encoding, '') old_content.sub!(encoding, '')
old_content.sub!(PATTERN, '')
new_content = (options[:position] || 'before').to_s == 'after' ? new_content = (options[:position] || 'before').to_s == 'after' ?
(encoding_header + (old_content.rstrip + "\n\n" + info_block)) : (encoding_header + (old_content.rstrip + "\n\n" + info_block)) :
(encoding_header + info_block + old_content) (encoding_header + info_block + old_content)
end
File.open(file_name, "wb") { |f| f.puts new_content } File.open(file_name, "wb") { |f| f.puts new_content }
true true
...@@ -162,7 +179,7 @@ module AnnotateModels ...@@ -162,7 +179,7 @@ module AnnotateModels
if File.exist?(file_name) if File.exist?(file_name)
content = File.read(file_name) content = File.read(file_name)
content.sub!(/^# #{COMPAT_PREFIX}.*?\n(#.*\n)*\n*/, '') content.sub!(PATTERN, '')
File.open(file_name, "wb") { |f| f.puts content } File.open(file_name, "wb") { |f| f.puts content }
end end
...@@ -198,11 +215,14 @@ module AnnotateModels ...@@ -198,11 +215,14 @@ module AnnotateModels
unless options[:exclude_fixtures] unless options[:exclude_fixtures]
[ [
File.join(FIXTURE_TEST_DIR, "#{klass.table_name}.yml"), # fixture
File.join(FIXTURE_SPEC_DIR, "#{klass.table_name}.yml"), # fixture
File.join(EXEMPLARS_TEST_DIR, "#{model_name}_exemplar.rb"), # Object Daddy File.join(EXEMPLARS_TEST_DIR, "#{model_name}_exemplar.rb"), # Object Daddy
File.join(EXEMPLARS_SPEC_DIR, "#{model_name}_exemplar.rb"), # Object Daddy File.join(EXEMPLARS_SPEC_DIR, "#{model_name}_exemplar.rb"), # Object Daddy
File.join(BLUEPRINTS_DIR, "#{model_name}_blueprint.rb"), # Machinist Blueprints File.join(BLUEPRINTS_TEST_DIR, "#{model_name}_blueprint.rb"), # Machinist Blueprints
File.join(FACTORIES_TEST_DIR, "#{model_name.pluralize}.rb"), # FactoryGirl Factories File.join(BLUEPRINTS_SPEC_DIR, "#{model_name}_blueprint.rb"), # Machinist Blueprints
File.join(FACTORIES_SPEC_DIR, "#{model_name.pluralize}.rb"), # FactoryGirl Factories File.join(FACTORY_GIRL_TEST_DIR, "#{model_name}_factory.rb"), # Factory Girl Factories
File.join(FACTORY_GIRL_SPEC_DIR, "#{model_name}_factory.rb"), # Factory Girl Factories
File.join(FABRICATORS_TEST_DIR, "#{model_name}_fabricator.rb"), # Fabrication Fabricators File.join(FABRICATORS_TEST_DIR, "#{model_name}_fabricator.rb"), # Fabrication Fabricators
File.join(FABRICATORS_SPEC_DIR, "#{model_name}_fabricator.rb"), # Fabrication Fabricators File.join(FABRICATORS_SPEC_DIR, "#{model_name}_fabricator.rb"), # Fabrication Fabricators
].each do |file| ].each do |file|
...@@ -210,15 +230,6 @@ module AnnotateModels ...@@ -210,15 +230,6 @@ module AnnotateModels
annotated = true annotated = true
end end
end end
FIXTURE_DIRS.each do |dir|
fixture_file_name = File.join(dir,klass.table_name + ".yml")
if File.exist?(fixture_file_name)
if annotate_one_file(fixture_file_name, info, options_with_position(options, :position_in_fixture))
annotated = true
end
end
end
end end
annotated annotated
...@@ -253,7 +264,9 @@ module AnnotateModels ...@@ -253,7 +264,9 @@ module AnnotateModels
models models
end end
# Retrieve model class from the given file. # Retrieve the classes belonging to the model names we're asked to process
# Check for namespaced models in subdirectories as well as models
# in subdirectories without namespacing.
def get_model_class(file) def get_model_class(file)
# this is for non-rails projects, which don't get Rails auto-require magic # this is for non-rails projects, which don't get Rails auto-require magic
require File.expand_path("#{model_dir}/#{file}") unless Module.const_defined?(:Rails) require File.expand_path("#{model_dir}/#{file}") unless Module.const_defined?(:Rails)
...@@ -303,10 +316,7 @@ module AnnotateModels ...@@ -303,10 +316,7 @@ module AnnotateModels
end end
end end
rescue Exception => e rescue Exception => e
puts "Unable to annotate #{file}: #{e.inspect}" puts "Unable to annotate #{file}: #{e.message} (#{e.backtrace.first})"
puts ""
# todo: check if all backtrace lines are in "gems" -- if so, it's an annotate bug, so print the whole stack trace.
# puts e.backtrace.join("\n\t")
end end
end end
if annotated.empty? if annotated.empty?
...@@ -328,16 +338,24 @@ module AnnotateModels ...@@ -328,16 +338,24 @@ module AnnotateModels
if klass < ActiveRecord::Base && !klass.abstract_class? if klass < ActiveRecord::Base && !klass.abstract_class?
deannotated << klass deannotated << klass
model_name = klass.name.underscore
model_file_name = File.join(model_dir, file) model_file_name = File.join(model_dir, file)
remove_annotation_of_file(model_file_name) remove_annotation_of_file(model_file_name)
FIXTURE_DIRS.each do |dir| [
fixture_file_name = File.join(dir,klass.table_name + ".yml") File.join(UNIT_TEST_DIR, "#{model_name}_test.rb"),
remove_annotation_of_file(fixture_file_name) if File.exist?(fixture_file_name) File.join(SPEC_MODEL_DIR, "#{model_name}_spec.rb"),
end File.join(FIXTURE_TEST_DIR, "#{klass.table_name}.yml"), # fixture
File.join(FIXTURE_SPEC_DIR, "#{klass.table_name}.yml"), # fixture
[ find_test_file(UNIT_TEST_DIR, "#{klass.name.underscore}_test.rb"), File.join(EXEMPLARS_TEST_DIR, "#{model_name}_exemplar.rb"), # Object Daddy
find_test_file(SPEC_MODEL_DIR,"#{klass.name.underscore}_spec.rb")].each do |file| File.join(EXEMPLARS_SPEC_DIR, "#{model_name}_exemplar.rb"), # Object Daddy
File.join(BLUEPRINTS_TEST_DIR, "#{model_name}_blueprint.rb"), # Machinist Blueprints
File.join(BLUEPRINTS_SPEC_DIR, "#{model_name}_blueprint.rb"), # Machinist Blueprints
File.join(FACTORY_GIRL_TEST_DIR, "#{model_name}_factory.rb"), # Factory Girl Factories
File.join(FACTORY_GIRL_SPEC_DIR, "#{model_name}_factory.rb"), # Factory Girl Factories
File.join(FABRICATORS_TEST_DIR, "#{model_name}_fabricator.rb"), # Fabrication Fabricators
File.join(FABRICATORS_SPEC_DIR, "#{model_name}_fabricator.rb"), # Fabrication Fabricators
].each do |file|
remove_annotation_of_file(file) if File.exist?(file) remove_annotation_of_file(file) if File.exist?(file)
end end
......
...@@ -8,6 +8,7 @@ task :annotate_models => :environment do ...@@ -8,6 +8,7 @@ task :annotate_models => :environment do
options={} options={}
options[:position_in_class] = ENV['position_in_class'] || ENV['position'] || 'before' options[:position_in_class] = ENV['position_in_class'] || ENV['position'] || 'before'
options[:position_in_fixture] = ENV['position_in_fixture'] || ENV['position'] || 'before' options[:position_in_fixture] = ENV['position_in_fixture'] || ENV['position'] || 'before'
options[:position_in_factory] = ENV['position_in_factory'] || ENV['position'] || 'before'
options[:show_indexes] = ENV['show_indexes'] =~ true_re options[:show_indexes] = ENV['show_indexes'] =~ true_re
options[:simple_indexes] = ENV['simple_indexes'] =~ true_re options[:simple_indexes] = ENV['simple_indexes'] =~ true_re
options[:model_dir] = ENV['model_dir'] options[:model_dir] = ENV['model_dir']
......
desc "Prepends the route map to the top of routes.rb" desc "Prepends the route map to the top of routes.rb"
task :annotate_routes do task :annotate_routes => :environment do
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'annotate', 'annotate_routes')) require File.expand_path(File.join(File.dirname(__FILE__), '..', 'annotate', 'annotate_routes'))
AnnotateRoutes.do_annotate AnnotateRoutes.do_annotate
end end
#encoding: utf-8
require File.dirname(__FILE__) + '/../spec_helper.rb' require File.dirname(__FILE__) + '/../spec_helper.rb'
require 'annotate/annotate_models' require 'annotate/annotate_models'
require 'annotate/active_record_patch' require 'annotate/active_record_patch'
require 'rubygems'
require 'active_support'
describe AnnotateModels do describe AnnotateModels do
def mock_class(table_name, primary_key, columns)
options = {
:connection => mock("Conn", :indexes => []),
:table_name => table_name,
:primary_key => primary_key.to_s,
:column_names => columns.map { |col| col.name.to_s },
:columns => columns
}
def mock_klass(stubs={}) mock("An ActiveRecord class", options)
@mock_file ||= mock("Klass", stubs)
end end
def mock_column(stubs={}) def mock_column(name, type, options={})
@mock_column ||= mock("Column", stubs) default_options = {
:limit => nil,
:null => false,
:default => nil
}
stubs = default_options.dup
stubs.merge!(options)
stubs.merge!(:name => name, :type => type)
mock("Column", stubs)
end end
it { AnnotateModels.quote(nil).should eql("NULL") } it { AnnotateModels.quote(nil).should eql("NULL") }
...@@ -22,43 +38,54 @@ describe AnnotateModels do ...@@ -22,43 +38,54 @@ describe AnnotateModels do
it { AnnotateModels.quote(1e-20).should eql("1.0e-20") } it { AnnotateModels.quote(1e-20).should eql("1.0e-20") }
it "should get schema info" do it "should get schema info" do
klass = mock_class(:users, :id, [
mock_column(:id, :integer),
mock_column(:name, :string, :limit => 50)
])
AnnotateModels.get_schema_info(mock_klass( AnnotateModels.get_schema_info(klass, "Schema Info").should eql(<<-EOS)
:connection => mock("Conn", :indexes => []),
:table_name => "users",
:primary_key => "id",
:column_names => ["id","login"],
:columns => [
mock_column(:type => "integer", :default => nil, :null => false, :name => "id", :limit => nil),
mock_column(:type => "string", :default => nil, :null => false, :name => "name", :limit => 50)
]), "Schema Info").should eql(<<-EOS)
# Schema Info # Schema Info
# #
# Table name: users # Table name: users
# #
# id :integer not null, primary key # id :integer not null, primary key
# id :integer not null, primary key # name :string(50) not null
# #
EOS EOS
end
it "should get schema info as RDoc" do
klass = mock_class(:users, :id, [
mock_column(:id, :integer),
mock_column(:name, :string, :limit => 50)
])
ENV.stub!(:[]).with('format_rdoc').and_return(true)
AnnotateModels.get_schema_info(klass, AnnotateModels::PREFIX).should eql(<<-EOS)
# #{AnnotateModels::PREFIX}
#
# Table name: users
#
# *id*:: <tt>integer, not null, primary key</tt>
# *name*:: <tt>string(50), not null</tt>
#--
# #{AnnotateModels::END_MARK}
#++
EOS
end end
describe "#get_model_class" do describe "#get_model_class" do
require "tmpdir" require "tmpdir"
module ::ActiveRecord
class Base
end
end
def create(file, body="hi") def create(file, body="hi")
file_path = File.join(AnnotateModels.model_dir, file) file_path = File.join(AnnotateModels.model_dir, file)
FileUtils.mkdir_p(File.dirname(file_path)) FileUtils.mkdir_p(File.dirname(file_path))
File.open(file_path, "w") do |f| File.open(file_path, "wb") do |f|
f.puts(body) f.puts(body)
end end
file_path
end end
def check_class_name(file, class_name) def check_class_name(file, class_name)
...@@ -80,15 +107,6 @@ EOS ...@@ -80,15 +107,6 @@ EOS
check_class_name 'foo.rb', 'Foo' check_class_name 'foo.rb', 'Foo'
end end
it "should not care about unknown macros" do
create 'foo_with_macro.rb', <<-EOS
class FooWithMacro < ActiveRecord::Base
acts_as_awesome :yah
end
EOS
check_class_name 'foo_with_macro.rb', 'FooWithMacro'
end
it "should find models with non standard capitalization" do it "should find models with non standard capitalization" do
create 'foo_with_capitals.rb', <<-EOS create 'foo_with_capitals.rb', <<-EOS
class FooWithCAPITALS < ActiveRecord::Base class FooWithCAPITALS < ActiveRecord::Base
...@@ -107,6 +125,25 @@ EOS ...@@ -107,6 +125,25 @@ EOS
check_class_name 'bar/foo_inside_bar.rb', 'Bar::FooInsideBar' check_class_name 'bar/foo_inside_bar.rb', 'Bar::FooInsideBar'
end end
it "should not care about unknown macros" do
create 'foo_with_macro.rb', <<-EOS
class FooWithMacro < ActiveRecord::Base
acts_as_awesome :yah
end
EOS
check_class_name 'foo_with_macro.rb', 'FooWithMacro'
end
it "should not complain of invalid multibyte char (USASCII)" do
create 'foo_with_utf8.rb', <<-EOS
#encoding: utf-8
class FooWithUtf8 < ActiveRecord::Base
UTF8STRINGS = %w[résumé façon âge]
end
EOS
check_class_name 'foo_with_utf8.rb', 'FooWithUtf8'
end
it "should find models inside modules with non standard capitalization" do it "should find models inside modules with non standard capitalization" do
create 'bar/foo_inside_capitals_bar.rb', <<-EOS create 'bar/foo_inside_capitals_bar.rb', <<-EOS
module BAR module BAR
...@@ -132,61 +169,114 @@ EOS ...@@ -132,61 +169,114 @@ EOS
EOS EOS
check_class_name 'bar/non_namespaced_foo_with_capitals_inside_bar.rb', 'NonNamespacedFooWithCapitalsInsideBar' check_class_name 'bar/non_namespaced_foo_with_capitals_inside_bar.rb', 'NonNamespacedFooWithCapitalsInsideBar'
end end
end
it "should not get confused by existing annotations on a model when the schema changes" do describe "#remove_annotation_of_file" do
create 'foo.rb', <<-EOS require "tmpdir"
class Foo < ActiveRecord::Base
end
# == Schema Information
#
# Table name: users
#
# id :integer(4) not null, primary key
# name :string
#
# Indexes
#
# index_users_on_name (name) UNIQUE
#
EOS def create(file, body="hi")
path = File.join(@dir, file)
File.open(path, "w") do |f|
f.puts(body)
end
return path
end
info_block = <<-EOS def content(path)
File.read(path)
end
before :each do
@dir = Dir.mktmpdir 'annotate_models'
end
it "should remove before annotate" do
path = create "before.rb", <<-EOS
# == Schema Information # == Schema Information
# #
# Table name: users # Table name: foo
#
# id :integer(4) not null, primary key
# name :string
# new :string
# #
# Indexes # id :integer not null, primary key
# # created_at :datetime
# index_users_on_name (name) UNIQUE # updated_at :datetime
# #
EOS class Foo < ActiveRecord::Base
fname = File.join(AnnotateModels.model_dir, 'foo.rb') end
EOS
AnnotateModels.annotate_one_file(fname, info_block).should be_true AnnotateModels.remove_annotation_of_file(path)
content(path).should == <<-EOS
class Foo < ActiveRecord::Base
end
EOS
end
File.read(fname).should == <<-EOS it "should remove after annotate" do
path = create "after.rb", <<-EOS
class Foo < ActiveRecord::Base class Foo < ActiveRecord::Base
end end
# == Schema Information # == Schema Information
# #
# Table name: users # Table name: foo
#
# id :integer(4) not null, primary key
# name :string
# new :string
#
# Indexes
# #
# index_users_on_name (name) UNIQUE # id :integer not null, primary key
# created_at :datetime
# updated_at :datetime
# #
EOS EOS
AnnotateModels.remove_annotation_of_file(path)
content(path).should == <<-EOS
class Foo < ActiveRecord::Base
end
EOS
end
end
describe "annotating a file" do
before do
@file_name = File.join(Dir.mktmpdir('annotate_models'), "user.rb")
@file_content = <<-EOS
class User < ActiveRecord::Base
end
EOS
File.open(@file_name, "wb") { |f| f.write @file_content }
@klass = mock_class(:users, :id, [
mock_column(:id, :integer),
mock_column(:name, :string, :limit => 50)
])
@schema_info = AnnotateModels.get_schema_info(@klass, "== Schema Info")
end
it "should annotate the file before the model if position == 'before'" do
AnnotateModels.annotate_one_file(@file_name, @schema_info, :position => "before")
File.read(@file_name).should == "#{@schema_info}#{@file_content}"
end
it "should annotate before if given :position => :before" do
AnnotateModels.annotate_one_file(@file_name, @schema_info, :position => :before)
File.read(@file_name).should == "#{@schema_info}#{@file_content}"
end
it "should annotate before if given :position => :after" do
AnnotateModels.annotate_one_file(@file_name, @schema_info, :position => :after)
File.read(@file_name).should == "#{@file_content}\n#{@schema_info}"
end
it "should update annotate position" do
AnnotateModels.annotate_one_file(@file_name, @schema_info, :position => :before)
another_schema_info = AnnotateModels.get_schema_info(mock_class(:users, :id, [mock_column(:id, :integer),]),
"== Schema Info")
AnnotateModels.annotate_one_file(@file_name, another_schema_info, :position => :after)
File.read(@file_name).should == "#{@file_content}\n#{another_schema_info}"
end end
end end
end end
--format=specdoc
--colour --colour
\ No newline at end of file
...@@ -7,5 +7,6 @@ rescue LoadError ...@@ -7,5 +7,6 @@ rescue LoadError
end end
$:.unshift(File.dirname(__FILE__) + '/../lib') $:.unshift(File.dirname(__FILE__) + '/../lib')
require 'bigdecimal' require 'active_support'
require 'active_support/core_ext/string/inflections'
require 'annotate' require 'annotate'
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