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
group :development do
gem 'jeweler'
gem 'rspec'
gem 'fakefs', :require => false
end
gem 'active_support'
gem 'activesupport', :require => nil
......@@ -5,6 +5,7 @@ GEM
activesupport (= 3.0.0)
activesupport (3.0.0)
diff-lcs (1.1.3)
fakefs (0.4.0)
git (1.2.5)
jeweler (1.6.4)
bundler (~> 1.0)
......@@ -25,5 +26,6 @@ PLATFORMS
DEPENDENCIES
active_support
fakefs
jeweler
rspec
......@@ -24,6 +24,20 @@
* Rename "annotate" bin to "annotate_models" to avoid conflicting with
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
* New options
......
......@@ -8,6 +8,7 @@ Add a comment summarizing the current schema to the top or bottom of each of you
* Object Daddy exemplars
* Machinist blueprints
* Fabrication fabricators
* Thoughtbot's factory_girl factories, i.e. the (spec|test)/factories/<model>_factory.rb files
The schema comment looks like this:
......@@ -96,7 +97,8 @@ you can use to tailor the output.
-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
-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
......@@ -110,7 +112,7 @@ to an automatically created comment block.
== 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
* Machinist => http://github.com/notahat/machinist
* Fabrication => http://github.com/paulelliott/fabrication
......@@ -144,6 +146,7 @@ Modifications by:
- Bob Potter - http://github.com/bpot
- Gavin Montague - http://github.com/govan/
- Alexander Semyonov - http://github.com/rotuka/
- Nathan Brazil - http://github.com/bitaxis/
- Ian Duggan http://github.com/ijcd/
- Jon Frisby http://github.com/mrjoy/
......
......@@ -32,12 +32,6 @@ RSpec::Core::RakeTask.new(:spec) do |t|
t.pattern = ['spec/*_spec.rb', 'spec/**/*_spec.rb']
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 throws "uninitialized constant RDoc::VISIBILITIES"
# require 'rdoc/task'
......
---
:major: 2
:minor: 4
:patch: 1
:build: 'beta1'
\ No newline at end of file
:patch: 2
......@@ -5,13 +5,14 @@
Gem::Specification.new do |s|
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.date = "2012-03-01"
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.executables = ["annotate_models"]
s.extra_rdoc_files = [
"README.rdoc"
]
......@@ -24,6 +25,7 @@ Gem::Specification.new do |s|
"Rakefile",
"VERSION.yml",
"annotate.gemspec",
"bin/annotate_models",
"lib/annotate.rb",
"lib/annotate/active_record_patch.rb",
"lib/annotate/annotate_models.rb",
......
......@@ -10,48 +10,48 @@ task = :annotate_models
OptionParser.new do |opts|
opts.banner = "Usage: annotate_models [options] [model_file]*"
opts.on('-d', '--delete',
"Remove annotations from all model files") do
opts.on('-d', '--delete',
"Remove annotations from all model files") do
task = :remove_annotation
end
opts.on('-p', '--position [before|after]', ['before', 'after'],
"Place the annotations at the top (before) or the bottom (after) of the model file") do |p|
opts.on('-p', '--position [before|after]', ['before', 'after'],
"Place the annotations at the top (before) or the bottom (after) of the model file") do |p|
ENV['position'] = p
end
opts.on('-r', '--routes',
"Annotate routes.rb with the output of 'rake routes'") do
opts.on('-r', '--routes',
"Annotate routes.rb with the output of 'rake routes'") do
task = :annotate_routes
end
opts.on('-v', '--version',
"Show the current version of this gem") do
opts.on('-v', '--version',
"Show the current version of this gem") do
puts "annotate v#{Annotate.version}"; exit
end
opts.on('-m', '--show-migration',
"Include the migration version number in the annotation") do
opts.on('-m', '--show-migration',
"Include the migration version number in the annotation") do
ENV['include_version'] = "yes"
end
opts.on('-i', '--show-indexes',
"List the table's database indexes in the annotation") do
opts.on('-i', '--show-indexes',
"List the table's database indexes in the annotation") do
ENV['show_indexes'] = "yes"
end
opts.on('-s', '--simple-indexes',
"Concat the column's related indexes in the annotation") do
"Concat the column's related indexes in the annotation") do
ENV['simple_indexes'] = "yes"
end
opts.on('--model-dir dir',
"Annotate model files stored in dir rather than app/models") do |dir|
opts.on('--model-dir dir',
"Annotate model files stored in dir rather than app/models") do |dir|
ENV['model_dir'] = dir
end
opts.on('-R', '--require path',
"Additional files to require before loading models") do |path|
"Additional files to require before loading models") do |path|
if ENV['require']
ENV['require'] = ENV['require'] + ",#{path}"
else
......@@ -63,6 +63,10 @@ OptionParser.new do |opts|
exclusions.each { |exclusion| ENV["exclude_#{exclusion}"] = "yes" }
end
opts.on('-f', '--format [bare|rdoc]', ['bare', 'rdoc'], 'rdoc: render Schema Infomation as RDoc') do |fmt|
ENV['format_#{fmt}'] = 'yes'
end
end.parse!
if Annotate.load_tasks
......
$:.unshift(File.dirname(__FILE__)) unless
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
require 'yaml'
......
module AnnotateModels
class << self
# Annotate Models plugin use this header
COMPAT_PREFIX = "== Schema Info"
PREFIX = "== Schema Information"
FIXTURE_DIRS = ["test/fixtures","spec/fixtures"]
# File.join for windows reverse bar compat?
# I dont use windows, can`t test
UNIT_TEST_DIR = File.join("test", "unit" )
SPEC_MODEL_DIR = File.join("spec", "models")
# Object Daddy http://github.com/flogic/object_daddy
EXEMPLARS_TEST_DIR = File.join("test", "exemplars")
EXEMPLARS_SPEC_DIR = File.join("spec", "exemplars")
# Machinist http://github.com/notahat/machinist
BLUEPRINTS_DIR = File.join("test", "blueprints")
# FactoryGirl http://github.com/thoughtbot/factory_girl
FACTORIES_TEST_DIR = File.join("test", "factories")
FACTORIES_SPEC_DIR = File.join("spec", "factories")
# Fabrication https://github.com/paulelliott/fabrication.git
FABRICATORS_TEST_DIR = File.join("test", "fabricators")
FABRICATORS_SPEC_DIR = File.join("spec", "fabricators")
# Annotate Models plugin use this header
COMPAT_PREFIX = "== Schema Info"
PREFIX = "== Schema Information"
END_MARK = "== Schema Information End"
PATTERN = /\n?# #{COMPAT_PREFIX}.*?\n(#.*\n)*\n*/
# File.join for windows reverse bar compat?
# I dont use windows, can`t test
UNIT_TEST_DIR = File.join("test", "unit" )
SPEC_MODEL_DIR = File.join("spec", "models")
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_SPEC_DIR = File.join("spec", "exemplars")
# Machinist http://github.com/notahat/machinist
BLUEPRINTS_TEST_DIR = File.join("test", "blueprints")
BLUEPRINTS_SPEC_DIR = File.join("spec", "blueprints")
# Factory Girl http://github.com/thoughtbot/factory_girl
FACTORY_GIRL_TEST_DIR = File.join("test", "factories")
FACTORY_GIRL_SPEC_DIR = File.join("spec", "factories")
# Fabrication https://github.com/paulelliott/fabrication.git
FABRICATORS_TEST_DIR = File.join("test", "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
@model_dir || "app/models"
end
......@@ -33,14 +39,14 @@ module AnnotateModels
# Simple quoting for the default column value
def quote(value)
case value
when NilClass then "NULL"
when TrueClass then "TRUE"
when FalseClass then "FALSE"
when Float, Fixnum, Bignum then value.to_s
when NilClass then "NULL"
when TrueClass then "TRUE"
when FalseClass then "FALSE"
when Float, Fixnum, Bignum then value.to_s
# BigDecimals need to be output in a non-normalized form and quoted.
when BigDecimal then value.to_s('F')
else
value.inspect
when BigDecimal then value.to_s('F')
else
value.inspect
end
end
......@@ -49,22 +55,26 @@ module AnnotateModels
# each column. The line contains the column name,
# the type (and length), and any optional attributes
def get_schema_info(klass, header, options = {})
info = "# #{header}\n#\n"
info << "# Table name: #{klass.table_name}\n#\n"
info = "# #{header}\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 += 1
max_size = klass.column_names.map{|name| name.size}.max || 0
max_size += ENV['format_rdoc'] ? 5 : 1
klass.columns.sort_by(&:name).each do |col|
attrs = []
attrs << "default(#{quote(col.default)})" unless col.default.nil?
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
if col_type == "decimal"
col_type << "(#{col.precision}, #{col.scale})"
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
# Check out if we got a geometric column
......@@ -85,14 +95,24 @@ module AnnotateModels
end
end
info << sprintf("# %-#{max_size}.#{max_size}s:%-15.15s %s", col.name, col_type, attrs.join(", ")).rstrip + "\n"
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"
end
end
if options[:show_indexes] && klass.table_exists?
info << get_index_info(klass)
end
info << "#\n\n"
if ENV['format_rdoc']
info << "#--\n"
info << "# #{END_MARK}\n"
info << "#++\n\n"
else
info << "#\n\n"
end
end
def get_index_info(klass)
......@@ -136,21 +156,18 @@ module AnnotateModels
old_columns = old_header && old_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
if old_columns == new_columns
false
else
# Replace the old schema info with the 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, '')
new_content = (options[:position] || 'before').to_s == 'after' ?
(encoding_header + (old_content.rstrip + "\n\n" + info_block)) :
(encoding_header + info_block + old_content)
end
# Strip the old schema info, and insert new schema info.
old_content.sub!(encoding, '')
old_content.sub!(PATTERN, '')
new_content = (options[:position] || 'before').to_s == 'after' ?
(encoding_header + (old_content.rstrip + "\n\n" + info_block)) :
(encoding_header + info_block + old_content)
File.open(file_name, "wb") { |f| f.puts new_content }
true
......@@ -162,7 +179,7 @@ module AnnotateModels
if File.exist?(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 }
end
......@@ -183,7 +200,7 @@ module AnnotateModels
if annotate_one_file(model_file_name, info, options_with_position(options, :position_in_class))
annotated = true
end
unless options[:exclude_tests]
[
find_test_file(UNIT_TEST_DIR, "#{model_name}_test.rb"), # test
......@@ -198,32 +215,26 @@ module AnnotateModels
unless options[:exclude_fixtures]
[
File.join(EXEMPLARS_TEST_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(FACTORIES_TEST_DIR, "#{model_name.pluralize}.rb"), # FactoryGirl Factories
File.join(FACTORIES_SPEC_DIR, "#{model_name.pluralize}.rb"), # FactoryGirl 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|
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_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|
if annotate_one_file(file, info, options_with_position(options, :position_in_fixture))
annotated = true
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
annotated
end
# position = :position_in_fixture or :position_in_class
def options_with_position(options, position_in)
options.merge(:position=>(options[position_in] || options[:position]))
......@@ -253,7 +264,9 @@ module AnnotateModels
models
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)
# 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)
......@@ -303,10 +316,7 @@ module AnnotateModels
end
end
rescue Exception => e
puts "Unable to annotate #{file}: #{e.inspect}"
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")
puts "Unable to annotate #{file}: #{e.message} (#{e.backtrace.first})"
end
end
if annotated.empty?
......@@ -328,19 +338,27 @@ module AnnotateModels
if klass < ActiveRecord::Base && !klass.abstract_class?
deannotated << klass
model_name = klass.name.underscore
model_file_name = File.join(model_dir, file)
remove_annotation_of_file(model_file_name)
FIXTURE_DIRS.each do |dir|
fixture_file_name = File.join(dir,klass.table_name + ".yml")
remove_annotation_of_file(fixture_file_name) if File.exist?(fixture_file_name)
end
[ find_test_file(UNIT_TEST_DIR, "#{klass.name.underscore}_test.rb"),
find_test_file(SPEC_MODEL_DIR,"#{klass.name.underscore}_spec.rb")].each do |file|
[
File.join(UNIT_TEST_DIR, "#{model_name}_test.rb"),
File.join(SPEC_MODEL_DIR, "#{model_name}_spec.rb"),
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_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)
end
end
rescue Exception => e
puts "Unable to annotate #{file}: #{e.message}"
......
......@@ -8,6 +8,7 @@ task :annotate_models => :environment do
options={}
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_factory] = ENV['position_in_factory'] || ENV['position'] || 'before'
options[:show_indexes] = ENV['show_indexes'] =~ true_re
options[:simple_indexes] = ENV['simple_indexes'] =~ true_re
options[:model_dir] = ENV['model_dir']
......
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'))
AnnotateRoutes.do_annotate
end
#encoding: utf-8
require File.dirname(__FILE__) + '/../spec_helper.rb'
require 'annotate/annotate_models'
require 'annotate/active_record_patch'
require 'rubygems'
require 'active_support'
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_file ||= mock("Klass", stubs)
mock("An ActiveRecord class", options)
end
def mock_column(stubs={})
@mock_column ||= mock("Column", stubs)
def mock_column(name, type, options={})
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
it { AnnotateModels.quote(nil).should eql("NULL") }
......@@ -22,43 +38,54 @@ describe AnnotateModels do
it { AnnotateModels.quote(1e-20).should eql("1.0e-20") }
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(
: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)
AnnotateModels.get_schema_info(klass, "Schema Info").should eql(<<-EOS)
# Schema Info
#
# 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
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
describe "#get_model_class" do
require "tmpdir"
module ::ActiveRecord
class Base
end
end
def create(file, body="hi")
file_path = File.join(AnnotateModels.model_dir, file)
FileUtils.mkdir_p(File.dirname(file_path))
File.open(file_path, "w") do |f|
File.open(file_path, "wb") do |f|
f.puts(body)
end
file_path
end
def check_class_name(file, class_name)
......@@ -80,15 +107,6 @@ EOS
check_class_name 'foo.rb', 'Foo'
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
create 'foo_with_capitals.rb', <<-EOS
class FooWithCAPITALS < ActiveRecord::Base
......@@ -107,6 +125,25 @@ EOS
check_class_name 'bar/foo_inside_bar.rb', 'Bar::FooInsideBar'
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
create 'bar/foo_inside_capitals_bar.rb', <<-EOS
module BAR
......@@ -132,61 +169,114 @@ EOS
EOS
check_class_name 'bar/non_namespaced_foo_with_capitals_inside_bar.rb', 'NonNamespacedFooWithCapitalsInsideBar'
end
end
it "should not get confused by existing annotations on a model when the schema changes" do
create 'foo.rb', <<-EOS
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
#
describe "#remove_annotation_of_file" do
require "tmpdir"
EOS
def create(file, body="hi")
path = File.join(@dir, file)
File.open(path, "w") do |f|
f.puts(body)
end
return path
end
def content(path)
File.read(path)
end
before :each do
@dir = Dir.mktmpdir 'annotate_models'
end
info_block = <<-EOS
it "should remove before annotate" do
path = create "before.rb", <<-EOS
# == Schema Information
#
# Table name: users
#
# id :integer(4) not null, primary key
# name :string
# new :string
#
# Indexes
# Table name: foo
#
# index_users_on_name (name) UNIQUE
# id :integer not null, primary key
# created_at :datetime
# updated_at :datetime
#
EOS
fname = File.join(AnnotateModels.model_dir, 'foo.rb')
class Foo < ActiveRecord::Base
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
end
# == Schema Information
#
# Table name: users
#
# id :integer(4) not null, primary key
# name :string
# new :string
#
# Indexes
# Table name: foo
#
# 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
--format=specdoc
--colour
\ No newline at end of file
......@@ -7,5 +7,6 @@ rescue LoadError
end
$:.unshift(File.dirname(__FILE__) + '/../lib')
require 'bigdecimal'
require 'active_support'
require 'active_support/core_ext/string/inflections'
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