schema_comments 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/LICENSE.txt +60 -0
- data/README +149 -0
- data/Rakefile +46 -0
- data/VERSION +1 -0
- data/autotest/discover.rb +10 -0
- data/init.rb +4 -0
- data/lib/annotate_models.rb +224 -0
- data/lib/schema_comments/base.rb +72 -0
- data/lib/schema_comments/connection_adapters.rb +170 -0
- data/lib/schema_comments/migration.rb +20 -0
- data/lib/schema_comments/migrator.rb +20 -0
- data/lib/schema_comments/schema.rb +20 -0
- data/lib/schema_comments/schema_comment.rb +195 -0
- data/lib/schema_comments/schema_dumper.rb +160 -0
- data/lib/schema_comments.rb +53 -0
- data/spec/.gitignore +3 -0
- data/spec/annotate_models_spec.rb +56 -0
- data/spec/database.yml +13 -0
- data/spec/fixtures/.gitignore +0 -0
- data/spec/i18n_export_spec.rb +48 -0
- data/spec/migration_spec.rb +96 -0
- data/spec/migrations/valid/001_create_products.rb +17 -0
- data/spec/migrations/valid/002_rename_products.rb +10 -0
- data/spec/migrations/valid/003_rename_products_again.rb +10 -0
- data/spec/migrations/valid/004_remove_price.rb +10 -0
- data/spec/migrations/valid/005_change_products_name.rb +10 -0
- data/spec/migrations/valid/006_change_products_name_with_comment.rb +10 -0
- data/spec/resources/models/product.rb +2 -0
- data/spec/resources/models/product_name.rb +2 -0
- data/spec/schema.rb +2 -0
- data/spec/schema_dumper_spec.rb +74 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +46 -0
- data/spec/yaml_export_spec.rb +52 -0
- data/tasks/annotate_models_tasks.rake +12 -0
- data/tasks/schema_comments.rake +204 -0
- metadata +115 -0
data/.gitignore
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
Ruby License
|
2
|
+
http://www.ruby-lang.org/en/LICENSE.txt
|
3
|
+
|
4
|
+
Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.co.jp>.
|
5
|
+
You can redistribute it and/or modify it under either the terms of the GPL
|
6
|
+
(see COPYING.txt file), or the conditions below:
|
7
|
+
|
8
|
+
1. You may make and give away verbatim copies of the source form of the
|
9
|
+
software without restriction, provided that you duplicate all of the
|
10
|
+
original copyright notices and associated disclaimers.
|
11
|
+
|
12
|
+
2. You may modify your copy of the software in any way, provided that
|
13
|
+
you do at least ONE of the following:
|
14
|
+
|
15
|
+
a) place your modifications in the Public Domain or otherwise
|
16
|
+
make them Freely Available, such as by posting said
|
17
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
18
|
+
the author to include your modifications in the software.
|
19
|
+
|
20
|
+
b) use the modified software only within your corporation or
|
21
|
+
organization.
|
22
|
+
|
23
|
+
c) rename any non-standard executables so the names do not conflict
|
24
|
+
with standard executables, which must also be provided.
|
25
|
+
|
26
|
+
d) make other distribution arrangements with the author.
|
27
|
+
|
28
|
+
3. You may distribute the software in object code or executable
|
29
|
+
form, provided that you do at least ONE of the following:
|
30
|
+
|
31
|
+
a) distribute the executables and library files of the software,
|
32
|
+
together with instructions (in the manual page or equivalent)
|
33
|
+
on where to get the original distribution.
|
34
|
+
|
35
|
+
b) accompany the distribution with the machine-readable source of
|
36
|
+
the software.
|
37
|
+
|
38
|
+
c) give non-standard executables non-standard names, with
|
39
|
+
instructions on where to get the original software distribution.
|
40
|
+
|
41
|
+
d) make other distribution arrangements with the author.
|
42
|
+
|
43
|
+
4. You may modify and include the part of the software into any other
|
44
|
+
software (possibly commercial). But some files in the distribution
|
45
|
+
are not written by the author, so that they are not under this terms.
|
46
|
+
|
47
|
+
They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
|
48
|
+
files under the ./missing directory. See each file for the copying
|
49
|
+
condition.
|
50
|
+
|
51
|
+
5. The scripts and library files supplied as input to or produced as
|
52
|
+
output from the software do not automatically fall under the
|
53
|
+
copyright of the software, but belong to whomever generated them,
|
54
|
+
and may be sold commercially, and may be aggregated with this
|
55
|
+
software.
|
56
|
+
|
57
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
58
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
59
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
60
|
+
PURPOSE.
|
data/README
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
SchemaComments
|
2
|
+
==========
|
3
|
+
|
4
|
+
== Install ==
|
5
|
+
|
6
|
+
=== as a plugin
|
7
|
+
ruby script/plugin install git://github.com/akm/schema_comments.git
|
8
|
+
|
9
|
+
=== as a gem
|
10
|
+
insert following line to config/environment.rb
|
11
|
+
config.gem 'schema_comments', :version => '0.1.0'
|
12
|
+
and
|
13
|
+
$ sudo rake gems:install
|
14
|
+
|
15
|
+
Or install gem manually
|
16
|
+
|
17
|
+
$ sudo gem install gemcutter
|
18
|
+
$ sudo gem tumble
|
19
|
+
$ sudo gem install schema_comments
|
20
|
+
|
21
|
+
== Configuration
|
22
|
+
If you install schema_comments as a gem, must create config/initializers/schema_comments.rb like this:
|
23
|
+
require 'schema_comments'
|
24
|
+
SchemaComments.setup
|
25
|
+
|
26
|
+
|
27
|
+
== overview ==
|
28
|
+
schema_commentsプラグインを使うと、テーブルとカラムにコメントを記述することができます。
|
29
|
+
|
30
|
+
class CreateProducts < ActiveRecord::Migration
|
31
|
+
def self.up
|
32
|
+
create_table "products", :comment => '商品' do |t|
|
33
|
+
t.string "product_type_cd", :comment => '種別コード'
|
34
|
+
t.integer "price", :comment => "価格"
|
35
|
+
t.string "name", :comment => "商品名"
|
36
|
+
t.datetime "created_at", :comment => "登録日時"
|
37
|
+
t.datetime "updated_at", :comment => "更新日時"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.down
|
42
|
+
drop_table "products"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
こんな感じ。
|
47
|
+
|
48
|
+
でこのようなマイグレーションを実行すると、db/schema.rb には、
|
49
|
+
コメントが設定されているテーブル、カラムは以下のように出力されます。
|
50
|
+
|
51
|
+
ActiveRecord::Schema.define(:version => 0) do
|
52
|
+
create_table "products", :force => true, :comment => '商品' do |t|
|
53
|
+
t.string "product_type_cd", :comment => '種別コード'
|
54
|
+
t.integer "price", :comment => "価格"
|
55
|
+
t.string "name", :comment => "商品名"
|
56
|
+
t.datetime "created_at", :comment => "登録日時"
|
57
|
+
t.datetime "updated_at", :comment => "更新日時"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
コメントは、以下のメソッドで使用することが可能です。
|
63
|
+
|
64
|
+
columns, create_table, drop_table, rename_table
|
65
|
+
remove_column, add_column, change_column
|
66
|
+
|
67
|
+
|
68
|
+
== コメントはどこに保存されるのか ==
|
69
|
+
db/schema_comments.yml にYAML形式で保存されます。
|
70
|
+
あまり推奨しませんが、もしマイグレーションにコメントを記述するのを忘れてしまった場合、db/schema_comments.yml
|
71
|
+
を直接編集した後、rake db:schema:dumpやマイグレーションを実行すると、db/schema.rbのコメントに反映されます。
|
72
|
+
|
73
|
+
|
74
|
+
== I18nへの対応 ==
|
75
|
+
rake i18n:schema_comments:update_config_localeタスクを実行すると、i18n用のYAMLを更新できます。
|
76
|
+
|
77
|
+
rake i18n:schema_comments:update_config_locale LOCALE=ja でデフォルトではconfig/locales/ja.ymlを更新します。
|
78
|
+
|
79
|
+
毎回LOCALEを指定するのが面倒な場合は、config/initializers/locale.rb に
|
80
|
+
I18n.default_locale = 'ja'
|
81
|
+
という記述を追加しておくと良いでしょう。
|
82
|
+
|
83
|
+
また出力先のYAMLのPATHを指定したい場合、YAML_PATHで指定が可能です。
|
84
|
+
rake i18n:schema_comments:update_config_locale LOCALE=ja YAML_PATH=/path/to/yaml
|
85
|
+
|
86
|
+
=== コメント内コメント ===
|
87
|
+
コメント中の ((( から ))) は反映されませんので、モデル名/属性名に含めたくない箇所は ((( と ))) で括ってください。
|
88
|
+
((( ))) と同様に[[[ ]]]も使用できます。
|
89
|
+
例えば以下のようにdb/schema.rbに出力されている場合、
|
90
|
+
ActiveRecord::Schema.define(:version => 0) do
|
91
|
+
create_table "products", :force => true, :comment => '商品' do |t|
|
92
|
+
t.string "product_type_cd", :comment => '種別コード(((01:書籍, 02:靴, 03:パソコン)))'
|
93
|
+
t.integer "price", :comment => "価格"
|
94
|
+
t.string "name", :comment => "商品名"
|
95
|
+
t.datetime "created_at", :comment => "登録日時"
|
96
|
+
t.datetime "updated_at", :comment => "更新日時"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
rake i18n:schema_comments:update_config_locale LOCALE=ja
|
101
|
+
とすると、以下のように出力されます。
|
102
|
+
ja:
|
103
|
+
activerecord:
|
104
|
+
attributes:
|
105
|
+
product:
|
106
|
+
product_type_cd: "種別コード"
|
107
|
+
price: "価格"
|
108
|
+
name: "商品名"
|
109
|
+
created_at: "登録日時"
|
110
|
+
updated_at: "更新日時"
|
111
|
+
|
112
|
+
|
113
|
+
|
114
|
+
== MySQLのビュー ==
|
115
|
+
MySQLのビューを使用した場合、元々MySQLではSHOW TABLES でビューも表示してしまうため、
|
116
|
+
ビューはテーブルとしてSchemaDumperに認識され、development環境ではMySQLのビューとして作成されているのに、
|
117
|
+
test環境ではテーブルとして作成されてしまい、テストが正しく動かないことがあります。
|
118
|
+
これを避けるため、schema_commentsでは、db/schema.rbを出力する際、テーブルに関する記述の後に、CREATE VIEWを行う記述を追加します。
|
119
|
+
|
120
|
+
|
121
|
+
== annotate_models ==
|
122
|
+
rake db:annotate で以下のようなコメントを、モデル、テスト、フィクスチャといったモデルに関係の強いファイルの
|
123
|
+
先頭に追加します。
|
124
|
+
# == Schema Info ==
|
125
|
+
#
|
126
|
+
# Schema version: 20090721185959
|
127
|
+
#
|
128
|
+
# Table name: books # 書籍
|
129
|
+
#
|
130
|
+
# id :integer not null, primary key
|
131
|
+
# title :string(100) not null # タイトル
|
132
|
+
# size :integer not null, default(1) # 判型
|
133
|
+
# price :decimal(17, 14) not null, default(0.0) # 価格
|
134
|
+
# created_at :datetime # 登録日時
|
135
|
+
# updated_at :datetime # 更新日時
|
136
|
+
#
|
137
|
+
# =================
|
138
|
+
#
|
139
|
+
|
140
|
+
また、rake db:updateで、rake db:migrateとrake db:annotateを実行します。
|
141
|
+
|
142
|
+
annotate_modelsは、達人プログラマーのDave Thomasさんが公開しているプラグインです。
|
143
|
+
http://repo.pragprog.com/svn/Public/plugins/annotate_models/
|
144
|
+
|
145
|
+
本プラグインでは、それを更に拡張したDave Boltonさんのプラグイン(
|
146
|
+
http://github.com/rotuka/annotate_models )をベースに拡張を加えています。
|
147
|
+
|
148
|
+
|
149
|
+
Copyright (c) 2008 Takeshi AKIMA, released under the Ruby License
|
data/Rakefile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "schema_comments"
|
8
|
+
gem.summary = "schema_comments generates extra methods dynamically"
|
9
|
+
gem.description = "schema_comments generates extra methods dynamically for attribute which has options"
|
10
|
+
gem.email = "akm2000@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/akm/schema_comments"
|
12
|
+
gem.authors = ["akimatter"]
|
13
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'spec/rake/spectask'
|
22
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
23
|
+
spec.libs << 'lib' << 'spec'
|
24
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
end
|
26
|
+
|
27
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
30
|
+
spec.rcov = true
|
31
|
+
end
|
32
|
+
|
33
|
+
task :spec => :check_dependencies
|
34
|
+
|
35
|
+
task :default => :spec
|
36
|
+
|
37
|
+
require 'rake/rdoctask'
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
40
|
+
|
41
|
+
rdoc.rdoc_dir = 'rdoc'
|
42
|
+
rdoc.title = "schema_comments #{version}"
|
43
|
+
rdoc.rdoc_files.include('README.rdoc')
|
44
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
45
|
+
rdoc.options = ["--charset", "utf-8", "--line-numbers"]
|
46
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/init.rb
ADDED
@@ -0,0 +1,224 @@
|
|
1
|
+
|
2
|
+
# fork from
|
3
|
+
# http://github.com/rotuka/annotate_models/blob/d2afee82020dbc592b147d92f9beeadbf665a9e0/lib/annotate_models.rb
|
4
|
+
|
5
|
+
require "config/environment" if File.exist?("config/environment")
|
6
|
+
|
7
|
+
MODEL_DIR = File.join(RAILS_ROOT, "app/models" )
|
8
|
+
UNIT_TEST_DIR = File.join(RAILS_ROOT, "test/unit" )
|
9
|
+
SPEC_MODEL_DIR = File.join(RAILS_ROOT, "spec/models")
|
10
|
+
FIXTURES_DIR = File.join(RAILS_ROOT, "test/fixtures")
|
11
|
+
SPEC_FIXTURES_DIR = File.join(RAILS_ROOT, "spec/fixtures")
|
12
|
+
|
13
|
+
module AnnotateModels
|
14
|
+
|
15
|
+
PREFIX_AT_BOTTOM = "== Schema Info"
|
16
|
+
SUFFIX_AT_BOTTOM = ""
|
17
|
+
PREFIX_ON_TOP = "== Schema Info =="
|
18
|
+
SUFFIX_ON_TOP = "=================\n# "
|
19
|
+
|
20
|
+
# ENV options
|
21
|
+
{:position => 'top', :model_dir => MODEL_DIR}.each do |name, default_value|
|
22
|
+
mattr_accessor name.to_sym
|
23
|
+
self.send("#{name}=", ENV[name.to_s.upcase] || default_value)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.models
|
27
|
+
(ENV['MODELS'] || '').split(',')
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.sort_columns
|
31
|
+
ENV['SORT'] =~ /yes|on|true/i
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.output_prefix
|
35
|
+
bottom? ? PREFIX_AT_BOTTOM : PREFIX_ON_TOP
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.output_suffix
|
39
|
+
bottom? ? SUFFIX_AT_BOTTOM : SUFFIX_ON_TOP
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.bottom?
|
43
|
+
self.position =~ /bottom/i
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.separate?
|
47
|
+
ENV['SEPARATE'] =~ /yes|on|true/i
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
# Simple quoting for the default column value
|
52
|
+
def self.quote(value)
|
53
|
+
case value
|
54
|
+
when NilClass then "NULL"
|
55
|
+
when TrueClass then "TRUE"
|
56
|
+
when FalseClass then "FALSE"
|
57
|
+
when Float, Fixnum, Bignum then value.to_s
|
58
|
+
# BigDecimals need to be output in a non-normalized form and quoted.
|
59
|
+
when BigDecimal then value.to_s('F')
|
60
|
+
else
|
61
|
+
value.inspect
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Use the column information in an ActiveRecord class
|
66
|
+
# to create a comment block containing a line for
|
67
|
+
# each column. The line contains the column name,
|
68
|
+
# the type (and length), and any optional attributes
|
69
|
+
def self.get_schema_info(klass)
|
70
|
+
table_info = "# Table name: #{klass.table_name}"
|
71
|
+
table_info << " # #{klass.table_comment}" unless klass.table_comment.blank?
|
72
|
+
table_info << "\n#\n"
|
73
|
+
max_size = klass.column_names.collect{|name| name.size}.max + 1
|
74
|
+
|
75
|
+
columns = klass.columns
|
76
|
+
|
77
|
+
cols = if self.sort_columns
|
78
|
+
pk = columns.find_all { |col| col.name == klass.primary_key }.flatten
|
79
|
+
assoc = columns.find_all { |col| col.name.match(/_id$/) }.sort_by(&:name)
|
80
|
+
dates = columns.find_all { |col| col.name.match(/_on$/) }.sort_by(&:name)
|
81
|
+
times = columns.find_all { |col| col.name.match(/_at$/) }.sort_by(&:name)
|
82
|
+
pk + assoc + (columns - pk - assoc - times - dates).compact.sort_by(&:name) + dates + times
|
83
|
+
else
|
84
|
+
columns
|
85
|
+
end
|
86
|
+
|
87
|
+
col_lines = append_comments(cols.map{|col| [col, annotate_column(col, klass, max_size)]})
|
88
|
+
cols_text = col_lines.join("\n")
|
89
|
+
|
90
|
+
result = "# #{self.output_prefix}\n# \n# Schema version: #{get_schema_version}\n#\n"
|
91
|
+
result << table_info
|
92
|
+
result << cols_text
|
93
|
+
result << "\n# \n# #{self.output_suffix}" unless self.output_suffix.blank?
|
94
|
+
result << "\n"
|
95
|
+
result
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.annotate_column(col, klass, max_size)
|
99
|
+
attrs = []
|
100
|
+
attrs << "not null" unless col.null
|
101
|
+
attrs << "default(#{quote(col.default)})" if col.default
|
102
|
+
attrs << "primary key" if col.name == klass.primary_key
|
103
|
+
|
104
|
+
col_type = col.type.to_s
|
105
|
+
if col_type == "decimal"
|
106
|
+
col_type << "(#{col.precision}, #{col.scale})"
|
107
|
+
else
|
108
|
+
col_type << "(#{col.limit})" if col.limit
|
109
|
+
end
|
110
|
+
sprintf("# %-#{max_size}s:%-15s %s", col.name, col_type, attrs.join(", ")).rstrip
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.append_comments(col_and_lines)
|
114
|
+
max_length = col_and_lines.map{|(col, line)| line.length}.max
|
115
|
+
col_and_lines.map do |(col, line)|
|
116
|
+
if col.comment.blank?
|
117
|
+
line
|
118
|
+
else
|
119
|
+
"%-#{max_length}s # %s" % [line, col.comment]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Add a schema block to a file. If the file already contains
|
125
|
+
# a schema info block (a comment starting
|
126
|
+
# with "Schema as of ..."), remove it first.
|
127
|
+
# Mod to write to the end of the file
|
128
|
+
def self.annotate_one_file(file_name, info_block)
|
129
|
+
if File.exist?(file_name)
|
130
|
+
content = File.read(file_name)
|
131
|
+
|
132
|
+
encoding_comment = content.scan(/^\#\s*-\*-(.+?)-\*-/).flatten.first
|
133
|
+
content.sub!(/^\#\s*-\*-(.+?)-\*-/, '')
|
134
|
+
|
135
|
+
# Remove old schema info
|
136
|
+
content.sub!(/(\n)*^# #{PREFIX_ON_TOP}.*?\n(#.*\n)*# #{SUFFIX_ON_TOP}/, '')
|
137
|
+
content.sub!(/(\n)*^# #{PREFIX_AT_BOTTOM}.*?\n(#.*\n)*#.*(\n)*/, '')
|
138
|
+
content.sub!(/^[\n\s]*/, '')
|
139
|
+
|
140
|
+
# Write it back
|
141
|
+
File.open(file_name, "w") do |f|
|
142
|
+
f.print "# -*- #{encoding_comment.strip} -*-\n\n" unless encoding_comment.blank?
|
143
|
+
if self.bottom?
|
144
|
+
f.print content
|
145
|
+
f.print "\n\n"
|
146
|
+
f.print info_block
|
147
|
+
else
|
148
|
+
f.print info_block
|
149
|
+
f.print "\n" if self.separate?
|
150
|
+
f.print content
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
# Given the name of an ActiveRecord class, create a schema
|
158
|
+
# info block (basically a comment containing information
|
159
|
+
# on the columns and their types) and put it at the front
|
160
|
+
# of the model and fixture source files.
|
161
|
+
def self.annotate(klass)
|
162
|
+
info = get_schema_info(klass)
|
163
|
+
model_name = klass.name.underscore
|
164
|
+
fixtures_name = "#{klass.table_name}.yml"
|
165
|
+
|
166
|
+
[
|
167
|
+
File.join(self.model_dir, "#{model_name}.rb"), # model
|
168
|
+
File.join(UNIT_TEST_DIR, "#{model_name}_test.rb"), # test
|
169
|
+
File.join(FIXTURES_DIR, fixtures_name), # fixture
|
170
|
+
File.join(SPEC_MODEL_DIR, "#{model_name}_spec.rb"), # spec
|
171
|
+
File.join(SPEC_FIXTURES_DIR, fixtures_name), # spec fixture
|
172
|
+
File.join(RAILS_ROOT, 'test', 'factories.rb'), # factories file
|
173
|
+
File.join(RAILS_ROOT, 'spec', 'factories.rb'), # factories file
|
174
|
+
].each { |file| annotate_one_file(file, info) }
|
175
|
+
end
|
176
|
+
|
177
|
+
# Return a list of the model files to annotate. If we have
|
178
|
+
# command line arguments, they're assumed to be either
|
179
|
+
# the underscore or CamelCase versions of model names.
|
180
|
+
# Otherwise we take all the model files in the
|
181
|
+
# app/models directory.
|
182
|
+
def self.get_model_names
|
183
|
+
result = nil
|
184
|
+
if self.models.empty?
|
185
|
+
Dir.chdir(self.model_dir) do
|
186
|
+
result = Dir["**/*.rb"].map do |filename|
|
187
|
+
filename.sub(/\.rb$/, '').camelize
|
188
|
+
end
|
189
|
+
end
|
190
|
+
else
|
191
|
+
result = self.models.dup
|
192
|
+
end
|
193
|
+
result
|
194
|
+
end
|
195
|
+
|
196
|
+
# We're passed a name of things that might be
|
197
|
+
# ActiveRecord models. If we can find the class, and
|
198
|
+
# if its a subclass of ActiveRecord::Base,
|
199
|
+
# then pas it to the associated block
|
200
|
+
def self.do_annotations
|
201
|
+
annotated = self.get_model_names.inject([]) do |list, class_name|
|
202
|
+
begin
|
203
|
+
# klass = class_name.split('::').inject(Object){ |klass,part| klass.const_get(part) }
|
204
|
+
klass = class_name.constantize
|
205
|
+
if klass < ActiveRecord::Base && !klass.abstract_class?
|
206
|
+
list << class_name
|
207
|
+
self.annotate(klass)
|
208
|
+
end
|
209
|
+
rescue Exception => e
|
210
|
+
puts "Unable to annotate #{class_name}: #{e.message}"
|
211
|
+
end
|
212
|
+
list
|
213
|
+
end
|
214
|
+
puts "Annotated #{annotated.join(', ')}"
|
215
|
+
end
|
216
|
+
|
217
|
+
def self.get_schema_version
|
218
|
+
unless @schema_version
|
219
|
+
version = ActiveRecord::Migrator.current_version rescue 0
|
220
|
+
@schema_version = version > 0 ? version : ''
|
221
|
+
end
|
222
|
+
@schema_version
|
223
|
+
end
|
224
|
+
end
|