lib/annotate_models.rb in schema_comments-0.1.4 vs lib/annotate_models.rb in schema_comments-0.2.0.alpha1
- old
+ new
@@ -1,19 +1,21 @@
# fork from
# http://github.com/rotuka/annotate_models/blob/d2afee82020dbc592b147d92f9beeadbf665a9e0/lib/annotate_models.rb
+require 'rails'
+
require "config/environment" if File.exist?("config/environment")
-MODEL_DIR = File.join(RAILS_ROOT, "app/models" )
-UNIT_TEST_DIR = File.join(RAILS_ROOT, "test/unit" )
-SPEC_MODEL_DIR = File.join(RAILS_ROOT, "spec/models")
-FIXTURES_DIR = File.join(RAILS_ROOT, "test/fixtures")
-SPEC_FIXTURES_DIR = File.join(RAILS_ROOT, "spec/fixtures")
+MODEL_DIR = Rails.root.join("app/models" )
+UNIT_TEST_DIR = Rails.root.join("test/unit" )
+SPEC_MODEL_DIR = Rails.root.join("spec/models")
+FIXTURES_DIR = Rails.root.join("test/fixtures")
+SPEC_FIXTURES_DIR = Rails.root.join("spec/fixtures")
module AnnotateModels
-
+
PREFIX_AT_BOTTOM = "== Schema Info"
SUFFIX_AT_BOTTOM = ""
PREFIX_ON_TOP = "== Schema Info =="
SUFFIX_ON_TOP = "=================\n# "
@@ -59,21 +61,21 @@
when BigDecimal then value.to_s('F')
else
value.inspect
end
end
-
+
# Use the column information in an ActiveRecord class
# to create a comment block containing a line for
# each column. The line contains the column name,
# the type (and length), and any optional attributes
def self.get_schema_info(klass)
table_info = "# Table name: #{klass.table_name}"
table_info << " # #{klass.table_comment}" unless klass.table_comment.blank?
table_info << "\n#\n"
max_size = klass.column_names.collect{|name| name.size}.max + 1
-
+
columns = klass.columns
cols = if self.sort_columns
pk = columns.find_all { |col| col.name == klass.primary_key }.flatten
assoc = columns.find_all { |col| col.name.match(/_id$/) }.sort_by(&:name)
@@ -81,28 +83,28 @@
times = columns.find_all { |col| col.name.match(/_at$/) }.sort_by(&:name)
pk + assoc + (columns - pk - assoc - times - dates).compact.sort_by(&:name) + dates + times
else
columns
end
-
+
col_lines = append_comments(cols.map{|col| [col, annotate_column(col, klass, max_size)]})
cols_text = col_lines.join("\n")
-
+
result = "# #{self.output_prefix}\n# \n# Schema version: #{get_schema_version}\n#\n"
result << table_info
result << cols_text
result << "\n# \n# #{self.output_suffix}" unless self.output_suffix.blank?
result << "\n"
result
end
-
+
def self.annotate_column(col, klass, max_size)
attrs = []
attrs << "not null" unless col.null
attrs << "default(#{quote(col.default)})" if col.default
attrs << "primary key" if col.name == klass.primary_key
-
+
col_type = col.type.to_s
if col_type == "decimal"
col_type << "(#{col.precision}, #{col.scale})"
else
col_type << "(#{col.limit})" if col.limit
@@ -118,27 +120,27 @@
else
"%-#{max_length}s # %s" % [line, col.comment]
end
end
end
-
+
# Add a schema block to a file. If the file already contains
# a schema info block (a comment starting
# with "Schema as of ..."), remove it first.
# Mod to write to the end of the file
def self.annotate_one_file(file_name, info_block)
if File.exist?(file_name)
content = File.read(file_name)
-
+
encoding_comment = content.scan(/^\#\s*-\*-(.+?)-\*-/).flatten.first
content.sub!(/^\#\s*-\*-(.+?)-\*-/, '')
# Remove old schema info
content.sub!(/(\n)*^# #{PREFIX_ON_TOP}.*?\n(#.*\n)*# #{SUFFIX_ON_TOP}/, '')
content.sub!(/(\n)*^# #{PREFIX_AT_BOTTOM}.*?\n(#.*\n)*#.*(\n)*/, '')
content.sub!(/^[\n\s]*/, '')
-
+
# Write it back
File.open(file_name, "w") do |f|
f.print "# -*- #{encoding_comment.strip} -*-\n\n" unless encoding_comment.blank?
if self.bottom?
f.print content
@@ -151,50 +153,50 @@
end
end
end
end
-
+
# Given the name of an ActiveRecord class, create a schema
# info block (basically a comment containing information
# on the columns and their types) and put it at the front
- # of the model and fixture source files.
+ # of the model and fixture source files.
def self.annotate(klass)
info = get_schema_info(klass)
model_name = klass.name.underscore
fixtures_name = "#{klass.table_name}.yml"
-
+
[
File.join(self.model_dir, "#{model_name}.rb"), # model
File.join(UNIT_TEST_DIR, "#{model_name}_test.rb"), # test
File.join(FIXTURES_DIR, fixtures_name), # fixture
File.join(SPEC_MODEL_DIR, "#{model_name}_spec.rb"), # spec
File.join(SPEC_FIXTURES_DIR, fixtures_name), # spec fixture
- File.join(RAILS_ROOT, 'test', 'factories.rb'), # factories file
- File.join(RAILS_ROOT, 'spec', 'factories.rb'), # factories file
+ Rails.root.join( 'test', 'factories.rb'), # factories file
+ Rails.root.join( 'spec', 'factories.rb'), # factories file
].each { |file| annotate_one_file(file, info) }
end
-
+
# Return a list of the model files to annotate. If we have
# command line arguments, they're assumed to be either
# the underscore or CamelCase versions of model names.
# Otherwise we take all the model files in the
# app/models directory.
def self.get_model_names
result = nil
if self.models.empty?
Dir.chdir(self.model_dir) do
- result = Dir["**/*.rb"].map do |filename|
+ result = Dir["**/*.rb"].map do |filename|
filename.sub(/\.rb$/, '').camelize
end
end
else
result = self.models.dup
end
- result
+ result
end
-
+
# We're passed a name of things that might be
# ActiveRecord models. If we can find the class, and
# if its a subclass of ActiveRecord::Base,
# then pas it to the associated block
def self.do_annotations
@@ -211,10 +213,10 @@
end
list
end
puts "Annotated #{annotated.join(', ')}"
end
-
+
def self.get_schema_version
unless @schema_version
version = ActiveRecord::Migrator.current_version rescue 0
@schema_version = version > 0 ? version : ''
end