migration_comments 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -4,8 +4,9 @@ Comments for your migrations
4
4
 
5
5
  Tested on:
6
6
 
7
- * Ruby 1.8.7/1.9.x using Rails 3.x
8
- * Ruby 1.8.6/1.8.7 using Rails 2.3.x.
7
+ Rails 4.x:: using Ruby 1.9.3 / 2.0
8
+ Rails 3.x:: using Ruby 1.8.7 / 1.9.x / 2.0
9
+ Rails 2.3.x (deprecated):: using 1.8.6 / 1.8.7
9
10
 
10
11
  == Why?
11
12
 
data/Rakefile CHANGED
@@ -1 +1,8 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << "test"
6
+ t.test_files = FileList['test/*_test.rb']
7
+ t.verbose = true
8
+ end
@@ -1,4 +1,5 @@
1
1
  require "migration_comments/version"
2
+ require "migration_comments/schema_formatter"
2
3
 
3
4
  require 'migration_comments/active_record/schema_dumper'
4
5
  require 'migration_comments/active_record/connection_adapters/comment_definition'
@@ -6,16 +7,24 @@ require 'migration_comments/active_record/connection_adapters/column_definition'
6
7
  require 'migration_comments/active_record/connection_adapters/column'
7
8
  require 'migration_comments/active_record/connection_adapters/table'
8
9
  require 'migration_comments/active_record/connection_adapters/table_definition'
10
+ require 'migration_comments/active_record/connection_adapters/alter_table'
9
11
  require 'migration_comments/active_record/connection_adapters/abstract_adapter'
12
+ require 'migration_comments/active_record/connection_adapters/abstract_adapter/schema_creation'
10
13
  require 'migration_comments/active_record/connection_adapters/mysql_adapter'
11
14
  require 'migration_comments/active_record/connection_adapters/mysql2_adapter'
12
15
  require 'migration_comments/active_record/connection_adapters/postgresql_adapter'
16
+ require 'migration_comments/active_record/connection_adapters/abstract_sqlite_adapter'
13
17
  require 'migration_comments/active_record/connection_adapters/sqlite_adapter'
18
+ require 'migration_comments/active_record/connection_adapters/sqlite3_adapter'
14
19
 
15
20
  require 'active_record/connection_adapters/abstract_adapter'
16
21
 
17
22
  module MigrationComments
18
23
  def self.setup
24
+ if ::ActiveRecord::VERSION::MAJOR == 2
25
+ warn "[DEPRECATION] MigrationComments support for ActiveRecord v2.3 is deprecated and will be removed in a future version."
26
+ end
27
+
19
28
  base_names = %w(SchemaDumper) +
20
29
  %w(ColumnDefinition Column Table TableDefinition AbstractAdapter).map{|name| "ConnectionAdapters::#{name}"}
21
30
 
@@ -27,10 +36,27 @@ module MigrationComments
27
36
  end
28
37
  end
29
38
 
30
- %w(PostgreSQL Mysql Mysql2 SQLite).each do |adapter|
39
+ # Rails 4 introduces some new models that were not previously present
40
+ optimistic_models = []
41
+ optimistic_models << "ActiveRecord::ConnectionAdapters::AbstractAdapter::SchemaCreation"
42
+ optimistic_models << "ActiveRecord::ConnectionAdapters::AlterTable"
43
+ optimistic_models.each do |model_name|
44
+ begin
45
+ model = model_name.constantize
46
+ mc_class = "MigrationComments::#{model_name}".constantize
47
+ model.module_eval do
48
+ model.send(:include, mc_class)
49
+ end
50
+ rescue Exception => ex
51
+ end
52
+ end
53
+
54
+ adapters = %w(PostgreSQL Mysql Mysql2)
55
+ adapters << (::ActiveRecord::VERSION::MAJOR <= 3 ? "SQLite" : "SQLite3")
56
+ adapters.each do |adapter|
31
57
  begin
32
58
  require("active_record/connection_adapters/#{adapter.downcase}_adapter")
33
- adapter_class = ('ActiveRecord::ConnectionAdapters::' << "#{adapter}Adapter").constantize
59
+ adapter_class = ('::ActiveRecord::ConnectionAdapters::' << "#{adapter}Adapter").constantize
34
60
  mc_class = ('MigrationComments::ActiveRecord::ConnectionAdapters::' << "#{adapter}Adapter").constantize
35
61
  adapter_class.module_eval do
36
62
  adapter_class.__send__(:include, mc_class)
@@ -19,6 +19,10 @@ module MigrationComments::ActiveRecord::ConnectionAdapters
19
19
  false
20
20
  end
21
21
 
22
+ def inline_comments?
23
+ false
24
+ end
25
+
22
26
  # Remove a comment on a table (if set)
23
27
  def remove_table_comment(table_name)
24
28
  set_table_comment(table_name, nil)
@@ -0,0 +1,40 @@
1
+ module MigrationComments::ActiveRecord::ConnectionAdapters::AbstractAdapter
2
+ module SchemaCreation
3
+ def self.included(base)
4
+ base.class_eval do
5
+ alias_method_chain :column_options, :migration_comments
6
+ alias_method_chain :visit_TableDefinition, :migration_comments
7
+ alias_method_chain :visit_ColumnDefinition, :migration_comments
8
+ end
9
+ end
10
+
11
+ def column_options_with_migration_comments(o)
12
+ column_options = o.primary_key? ? {} : column_options_without_migration_comments(o)
13
+ column_options[:comment] = o.comment.comment_text if o.comment
14
+ column_options
15
+ end
16
+
17
+ def visit_TableDefinition_with_migration_comments(o)
18
+ if @conn.inline_comments?
19
+ create_sql = "CREATE#{' TEMPORARY' if o.temporary} TABLE "
20
+ create_sql << "#{quote_table_name(o.name)}#{o.table_comment} ("
21
+ create_sql << o.columns.map { |c| accept c }.join(', ')
22
+ create_sql << ") #{o.options}"
23
+ create_sql
24
+ else
25
+ visit_TableDefinition_without_migration_comments(o)
26
+ end
27
+ end
28
+
29
+ def visit_ColumnDefinition_with_migration_comments(o)
30
+ if @conn.inline_comments?
31
+ sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
32
+ column_sql = "#{quote_column_name(o.name)} #{sql_type}"
33
+ add_column_options!(column_sql, column_options(o))
34
+ column_sql
35
+ else
36
+ visit_ColumnDefinition_without_migration_comments(o)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,85 @@
1
+ module MigrationComments::ActiveRecord::ConnectionAdapters
2
+ module AbstractSQLiteAdapter
3
+ def comments_supported?
4
+ true
5
+ end
6
+
7
+ def inline_comments?
8
+ true
9
+ end
10
+
11
+ def set_table_comment(table_name, comment_text)
12
+ alter_table(table_name, :comment => comment_text)
13
+ end
14
+
15
+ def set_column_comment(table_name, column_name, comment_text)
16
+ sql_type = primary_key(table_name) == column_name.to_s ?
17
+ :primary_key :
18
+ column_for(table_name, column_name).sql_type
19
+ change_column table_name, column_name, sql_type, :comment => comment_text
20
+ end
21
+
22
+ def retrieve_table_comment(table_name)
23
+ result = select_rows(lookup_comment_sql(table_name))
24
+ if result[0][0] =~ /CREATE (?:TEMPORARY )?TABLE #{quote_table_name table_name} [^\(]*\/\*(.*)\*\/ \(/
25
+ $1
26
+ end
27
+ end
28
+
29
+ def retrieve_column_comments(table_name, *column_names)
30
+ if column_names.empty?
31
+ return columns(table_name).inject({}) { |m, v| m[v.name.to_sym] = v.comment if v.comment.present?; m }
32
+ end
33
+ result = select_rows(lookup_comment_sql(table_name))
34
+ result[0][0] =~ /^CREATE (?:TEMPORARY )?TABLE "\w*" [^\(]*(?:\/\*.*\*\/ )?\((.*)\)[^\)]*$/
35
+ col_defs = $1
36
+ comment_matches = col_defs.scan(/"([^",]+)"[^,]*\/\*(.+?)\*\//)
37
+ comment_matches.inject({}){|m, row| m[row.first.to_sym] = row.last; m}
38
+ end
39
+
40
+ def change_column_with_migration_comments(table_name, column_name, type, options = {}) #:nodoc:
41
+ adapter = self
42
+ alter_table(table_name) do |definition|
43
+ include_default = options_include_default?(options)
44
+ definition[column_name].instance_eval do
45
+ self.type = type
46
+ self.limit = options[:limit] if options.include?(:limit)
47
+ self.default = options[:default] if include_default
48
+ self.null = options[:null] if options.include?(:null)
49
+ self.precision = options[:precision] if options.include?(:precision)
50
+ self.scale = options[:scale] if options.include?(:scale)
51
+ self.comment = CommentDefinition.new(adapter, table_name, column_name, options[:comment]) if options.include?(:comment)
52
+ end
53
+ end
54
+ end
55
+
56
+ def column_for(table_name, column_name)
57
+ columns(table_name).detect{|col| col.name == column_name.to_s}
58
+ end
59
+
60
+ def comment_sql(comment_definition)
61
+ if comment_definition.nil? || comment_definition.comment_text.blank?
62
+ ""
63
+ else
64
+ " /*#{escaped_comment(comment_definition.comment_text)}*/"
65
+ end
66
+
67
+ end
68
+
69
+ def add_column_options!(sql, options)
70
+ super(sql, options)
71
+ if options.keys.include?(:comment)
72
+ sql << CommentDefinition.new(self, nil, nil, options[:comment]).to_sql
73
+ end
74
+ end
75
+
76
+ private
77
+ def escaped_comment(comment)
78
+ comment.gsub(/\*\//, "*-/")
79
+ end
80
+
81
+ def lookup_comment_sql(table_name)
82
+ "select sql from (select * from sqlite_master where type='table' union select * from sqlite_temp_master where type='table') where tbl_name = '#{table_name}'"
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,17 @@
1
+ module MigrationComments::ActiveRecord::ConnectionAdapters
2
+ module AlterTable
3
+ def self.included(base)
4
+ base.class_eval do
5
+ alias_method_chain :add_column, :migration_comments
6
+ end
7
+ end
8
+
9
+ def add_column_with_migration_comments(name, type, options)
10
+ add_column_without_migration_comments(name, type, options)
11
+ if options.keys.include?(:comment)
12
+ column = @adds.last
13
+ column.comment = CommentDefinition.new(nil, @td, name, options[:comment])
14
+ end
15
+ end
16
+ end
17
+ end
@@ -2,12 +2,15 @@ module MigrationComments::ActiveRecord::ConnectionAdapters
2
2
  module MysqlAdapter
3
3
  def self.included(base)
4
4
  base.class_eval do
5
- attr_accessor :database_name
6
5
  alias_method_chain :create_table, :migration_comments
7
6
  alias_method_chain :change_column, :migration_comments
8
7
  end
9
8
  end
10
9
 
10
+ def comments_supported?
11
+ true
12
+ end
13
+
11
14
  def set_table_comment(table_name, comment_text)
12
15
  execute "ALTER TABLE #{quote_table_name table_name} COMMENT #{escaped_comment(comment_text)}"
13
16
  end
@@ -31,14 +34,14 @@ module MigrationComments::ActiveRecord::ConnectionAdapters
31
34
  def retrieve_column_comments(table_name, *column_names)
32
35
  result = select_rows(column_comment_sql(table_name, *column_names))
33
36
  return {} if result.nil?
34
- found = result.inject({}){|m, row| m[row[0].to_sym] = (row[1].blank? ? nil : row[1]); m}
35
-
37
+ result.inject({}){|m, row| m[row[0].to_sym] = (row[1].blank? ? nil : row[1]); m}
36
38
  end
37
39
 
38
40
  def create_table_with_migration_comments(table_name, options={}, &block)
39
41
  local_table_definition = nil
40
42
  create_table_without_migration_comments(table_name, options) do |td|
41
43
  local_table_definition = td
44
+ local_table_definition.base = self
42
45
  local_table_definition.comment options[:comment] if options.has_key?(:comment)
43
46
  block.call(td)
44
47
  end
@@ -76,7 +79,6 @@ module MigrationComments::ActiveRecord::ConnectionAdapters
76
79
  end
77
80
 
78
81
  def table_comment_sql(table_name)
79
- ensure_database_name
80
82
  <<SQL
81
83
  SELECT table_comment FROM INFORMATION_SCHEMA.TABLES
82
84
  WHERE table_schema = '#{database_name}'
@@ -85,7 +87,6 @@ SQL
85
87
  end
86
88
 
87
89
  def column_comment_sql(table_name, *column_names)
88
- ensure_database_name
89
90
  col_matcher_sql = column_names.empty? ? "" : " AND column_name IN (#{column_names.map{|c_name| "'#{c_name}'"}.join(',')})"
90
91
  <<SQL
91
92
  SELECT column_name, column_comment FROM INFORMATION_SCHEMA.COLUMNS
@@ -94,10 +95,8 @@ SELECT column_name, column_comment FROM INFORMATION_SCHEMA.COLUMNS
94
95
  SQL
95
96
  end
96
97
 
97
- def ensure_database_name
98
- return if database_name
99
- info = YAML::load(IO.read('config/database.yml'))
100
- @database_name = info[ENV['DB'] || Rails.env.to_s]["database"]
98
+ def database_name
99
+ @database_name ||= select_rows("SELECT DATABASE()")[0][0]
101
100
  end
102
101
 
103
102
  end
@@ -37,6 +37,7 @@ module MigrationComments::ActiveRecord::ConnectionAdapters
37
37
  local_table_definition = nil
38
38
  create_table_without_migration_comments(table_name, options) do |td|
39
39
  local_table_definition = td
40
+ local_table_definition.base = self
40
41
  local_table_definition.comment options[:comment] if options.has_key?(:comment)
41
42
  block.call(td)
42
43
  end
@@ -0,0 +1,75 @@
1
+ module MigrationComments::ActiveRecord::ConnectionAdapters
2
+ module SQLite3Adapter
3
+ include AbstractSQLiteAdapter
4
+
5
+ def self.included(base)
6
+ base.class_eval do
7
+ alias_method_chain :columns, :migration_comments
8
+ alias_method_chain :copy_table, :migration_comments
9
+ alias_method_chain :change_column, :migration_comments
10
+ end
11
+ end
12
+
13
+ def create_table(table_name, options = {})
14
+ td = create_table_definition table_name, options[:temporary], options[:options]
15
+ td.base = self
16
+
17
+ unless options[:id] == false
18
+ pk = options.fetch(:primary_key) {
19
+ ActiveRecord::Base.get_primary_key table_name.to_s.singularize
20
+ }
21
+
22
+ td.primary_key pk, options.fetch(:id, :primary_key), options
23
+ end
24
+ td.comment options[:comment] if options.has_key?(:comment)
25
+
26
+ yield td if block_given?
27
+
28
+ if options[:force] && table_exists?(table_name)
29
+ drop_table(table_name, options)
30
+ end
31
+
32
+ execute schema_creation.accept td
33
+ td.indexes.each_pair { |c,o| add_index table_name, c, o }
34
+ end
35
+
36
+ def columns_with_migration_comments(table_name)
37
+ cols = columns_without_migration_comments(table_name)
38
+ comments = retrieve_column_comments(table_name, *(cols.map(&:name)))
39
+ cols.each do |col|
40
+ col.comment = comments[col.name.to_sym] if comments.has_key?(col.name.to_sym)
41
+ end
42
+ cols
43
+ end
44
+
45
+ def copy_table_with_migration_comments(from, to, options = {}) #:nodoc:
46
+ from_primary_key = primary_key(from)
47
+ options[:id] = false
48
+ unless options.has_key?(:comment)
49
+ table_comment = retrieve_table_comment(from)
50
+ options = options.merge(:comment => table_comment) if table_comment
51
+ end
52
+ create_table(to, options) do |definition|
53
+ @definition = definition
54
+ @definition.primary_key(from_primary_key) if from_primary_key.present?
55
+ columns(from).each do |column|
56
+ column_name = options[:rename] ?
57
+ (options[:rename][column.name] ||
58
+ options[:rename][column.name.to_sym] ||
59
+ column.name) : column.name
60
+ next if column_name == from_primary_key
61
+
62
+ @definition.column(column_name, column.type,
63
+ :limit => column.limit, :default => column.default,
64
+ :precision => column.precision, :scale => column.scale,
65
+ :null => column.null, :comment => column.comment)
66
+ end
67
+ yield @definition if block_given?
68
+ end
69
+ copy_table_indexes(from, to, options[:rename] || {})
70
+ copy_table_contents(from, to,
71
+ @definition.columns.map {|column| column.name},
72
+ options[:rename] || {})
73
+ end
74
+ end
75
+ end
@@ -1,46 +1,20 @@
1
1
  module MigrationComments::ActiveRecord::ConnectionAdapters
2
2
  module SQLiteAdapter
3
+ include AbstractSQLiteAdapter
4
+
3
5
  def self.included(base)
4
- base.class_eval do
6
+ base.module_eval do
5
7
  alias_method_chain :columns, :migration_comments
6
8
  alias_method_chain :copy_table, :migration_comments
7
9
  alias_method_chain :change_column, :migration_comments
8
10
  end
9
11
  end
10
12
 
11
- def set_table_comment(table_name, comment_text)
12
- alter_table(table_name, :comment => comment_text)
13
- end
14
-
15
- def set_column_comment(table_name, column_name, comment_text)
16
- sql_type = primary_key(table_name) == column_name.to_s ?
17
- :primary_key :
18
- column_for(table_name, column_name).sql_type
19
- change_column table_name, column_name, sql_type, :comment => comment_text
20
- end
21
-
22
- def retrieve_table_comment(table_name)
23
- result = select_rows(lookup_comment_sql(table_name))
24
- if result[0][0] =~ /CREATE (?:TEMPORARY )?TABLE #{quote_table_name table_name} [^\(]*\/\*(.*)\*\/ \(/
25
- $1
26
- end
27
- end
28
-
29
- def retrieve_column_comments(table_name, *column_names)
30
- if column_names.empty?
31
- return columns(table_name).inject({}) { |m, v| m[v.name.to_sym] = v.comment if v.comment.present?; m }
32
- end
33
- result = select_rows(lookup_comment_sql(table_name))
34
- result[0][0] =~ /^CREATE (?:TEMPORARY )?TABLE "\w*" [^\(]*(?:\/\*.*\*\/ )?\((.*)\)[^\)]*$/
35
- col_defs = $1
36
- comment_matches = col_defs.scan(/"([^",]+)"[^,]*\/\*(.+?)\*\//)
37
- comment_matches.inject({}){|m, row| m[row.first.to_sym] = row.last; m}
38
- end
39
-
40
13
  def create_table(table_name, options = {})
41
- td = table_definition
14
+ td = ActiveRecord::ConnectionAdapters::TableDefinition.new(self)
42
15
  td.primary_key(options[:primary_key] || ActiveRecord::Base.get_primary_key(table_name.to_s.singularize)) unless options[:id] == false
43
16
  td.comment options[:comment] if options.has_key?(:comment)
17
+ td.base = self
44
18
 
45
19
  yield td if block_given?
46
20
 
@@ -57,22 +31,6 @@ module MigrationComments::ActiveRecord::ConnectionAdapters
57
31
  execute create_sql
58
32
  end
59
33
 
60
- def change_column_with_migration_comments(table_name, column_name, type, options = {}) #:nodoc:
61
- adapter = self
62
- alter_table(table_name) do |definition|
63
- include_default = options_include_default?(options)
64
- definition[column_name].instance_eval do
65
- self.type = type
66
- self.limit = options[:limit] if options.include?(:limit)
67
- self.default = options[:default] if include_default
68
- self.null = options[:null] if options.include?(:null)
69
- self.precision = options[:precision] if options.include?(:precision)
70
- self.scale = options[:scale] if options.include?(:scale)
71
- self.comment = CommentDefinition.new(adapter, table_name, column_name, options[:comment]) if options.include?(:comment)
72
- end
73
- end
74
- end
75
-
76
34
  def columns_with_migration_comments(table_name, name = nil)
77
35
  cols = columns_without_migration_comments(table_name, name)
78
36
  comments = retrieve_column_comments(table_name, *(cols.map(&:name)))
@@ -82,19 +40,6 @@ module MigrationComments::ActiveRecord::ConnectionAdapters
82
40
  cols
83
41
  end
84
42
 
85
- def column_for(table_name, column_name)
86
- columns(table_name).detect{|col| col.name == column_name.to_s}
87
- end
88
-
89
- def comment_sql(comment_definition)
90
- if comment_definition.nil? || comment_definition.comment_text.blank?
91
- ""
92
- else
93
- " /*#{escaped_comment(comment_definition.comment_text)}*/"
94
- end
95
-
96
- end
97
-
98
43
  def copy_table_with_migration_comments(from, to, options = {}) #:nodoc:
99
44
  options = options.merge(:id => (!columns(from).detect{|c| c.name == 'id'}.nil? && 'id' == primary_key(from).to_s))
100
45
  unless options.has_key?(:comment)
@@ -122,21 +67,5 @@ module MigrationComments::ActiveRecord::ConnectionAdapters
122
67
  @definition.columns.map {|column| column.name},
123
68
  options[:rename] || {})
124
69
  end
125
-
126
- def add_column_options!(sql, options)
127
- super(sql, options)
128
- if options.keys.include?(:comment)
129
- sql << CommentDefinition.new(self, nil, nil, options[:comment]).to_sql
130
- end
131
- end
132
-
133
- private
134
- def escaped_comment(comment)
135
- comment.gsub(/\*\//, "*-/")
136
- end
137
-
138
- def lookup_comment_sql(table_name)
139
- "select sql from (select * from sqlite_master where type='table' union select * from sqlite_temp_master where type='table') where tbl_name = '#{table_name}'"
140
- end
141
70
  end
142
71
  end
@@ -5,11 +5,12 @@ module MigrationComments::ActiveRecord::ConnectionAdapters
5
5
  def self.included(base)
6
6
  base.class_eval do
7
7
  alias_method_chain :column, :migration_comments
8
+ attr_accessor :base
8
9
  end
9
10
  end
10
11
 
11
12
  def comment(text)
12
- @table_comment = CommentDefinition.new(@base, nil, nil, text)
13
+ @table_comment = CommentDefinition.new(base, nil, nil, text)
13
14
  self
14
15
  end
15
16
 
@@ -17,16 +18,16 @@ module MigrationComments::ActiveRecord::ConnectionAdapters
17
18
  column_without_migration_comments(name, type, options)
18
19
  if options.has_key?(:comment)
19
20
  col = self[name]
20
- col.comment = CommentDefinition.new(@base, nil, name, options[:comment])
21
+ col.comment = CommentDefinition.new(base, nil, name, options[:comment])
21
22
  end
22
23
  self
23
24
  end
24
25
 
25
26
  def collect_comments(table_name)
26
27
  comments = []
27
- comments << @table_comment << @columns.map(&:comment)
28
+ comments << @table_comment << columns.map(&:comment)
28
29
  comments.flatten!.compact!
29
- comments.each{|comment| comment.table = table_name}
30
+ comments.each{|comment| comment.table = table_name; comment.adapter = base}
30
31
  end
31
32
  end
32
33
  end
@@ -1,5 +1,6 @@
1
1
  module MigrationComments::ActiveRecord
2
2
  module SchemaDumper
3
+ include MigrationComments::SchemaFormatter
3
4
  def self.included(base)
4
5
  base.class_eval do
5
6
  alias_method_chain :table, :migration_comments
@@ -23,9 +24,12 @@ module MigrationComments::ActiveRecord
23
24
  lines = []
24
25
  table_line = 0
25
26
  col_names = {}
27
+ error = false
26
28
  while (line = stream.gets)
27
29
  content = line.chomp
28
- if content =~ /create_table\s/
30
+ if content =~ /^# Could not dump table "#{table_name}"/
31
+ error = true
32
+ elsif content =~ /create_table\s/
29
33
  table_line = lines.size
30
34
  elsif content =~ /t\.\w+\s+"(\w+)"/
31
35
  col_names[lines.size] = $1.to_sym
@@ -34,7 +38,9 @@ module MigrationComments::ActiveRecord
34
38
  end
35
39
  len = col_names.keys.map{|index| lines[index]}.map(&:length).max + 2 unless col_names.empty?
36
40
  lines.each_with_index do |line, index|
37
- if table_line == index && table_comment.present?
41
+ if error
42
+ # do nothing
43
+ elsif table_line == index && table_comment.present?
38
44
  block_init = " do |t|"
39
45
  line.chomp!(block_init) << ", " << render_comment(table_comment) << block_init
40
46
  elsif col_names[index]
@@ -46,9 +52,5 @@ module MigrationComments::ActiveRecord
46
52
  comment_stream.rewind
47
53
  comment_stream
48
54
  end
49
-
50
- def render_comment(comment)
51
- ":comment => \"#{comment}\""
52
- end
53
55
  end
54
56
  end
@@ -0,0 +1,19 @@
1
+ module MigrationComments
2
+ module SchemaFormatter
3
+ def render_comment(comment)
4
+ render_kv_pair(:comment, comment)
5
+ end
6
+
7
+ def render_kv_pair(key, value)
8
+ if ::ActiveRecord::VERSION::MAJOR <= 3
9
+ ":#{key} => #{render_value(value)}"
10
+ else
11
+ "#{key}: #{render_value(value)}"
12
+ end
13
+ end
14
+
15
+ def render_value(value)
16
+ value.is_a?(String) ? "\"#{value}\"" : value
17
+ end
18
+ end
19
+ end
@@ -1,3 +1,3 @@
1
1
  module MigrationComments
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
6
6
  s.name = "migration_comments"
7
7
  s.version = MigrationComments::VERSION
8
8
  s.authors = ["Pinny"]
9
- s.email = ["pinny@medwiztech.com"]
9
+ s.email = ["pinny@mwitz.com"]
10
10
  s.homepage = "https://github.com/pinnymz/migration_comments"
11
11
  s.summary = %q{Comments for your migrations}
12
12
  s.description = %q{Add schema comments in your migrations, see them in model annotations and db/schema.rb dump}
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
 
21
- s.add_runtime_dependency 'rails', '>= 2.3.2'
21
+ s.add_runtime_dependency 'activerecord', '>= 2.3.2'
22
22
 
23
23
  # for development, we are testing against the 'annotate' gem
24
24
  # however, the comments should work with the original 'annotate_models' plugin as well at:
@@ -26,9 +26,10 @@ Gem::Specification.new do |s|
26
26
  # provided the environment is not loaded until _after_ the AnnotateModels module is declared
27
27
  s.add_development_dependency 'annotate', '~> 2.5.0'
28
28
 
29
- s.add_development_dependency 'pg' # replace with other adapter as needed
29
+ # add / replace with other adapter(s) as needed
30
+ s.add_development_dependency 'pg'
30
31
  # s.add_development_dependency 'postgres-pr'
31
32
  # s.add_development_dependency 'mysql'
32
- # s.add_development_dependency 'mysql2'
33
- # s.add_development_dependency 'sqlite3'
33
+ s.add_development_dependency 'mysql2'
34
+ s.add_development_dependency 'sqlite3'
34
35
  end
@@ -1,4 +1,4 @@
1
- require './test_helper'
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
2
 
3
3
  class AddCommentsTest < Test::Unit::TestCase
4
4
  include TestHelper
@@ -40,7 +40,7 @@ class AddCommentsTest < Test::Unit::TestCase
40
40
  result_table_comment = retrieve_table_comment :sample2
41
41
  result_column_comments = retrieve_column_comments :sample2
42
42
  ensure
43
- drop_table :sample2
43
+ drop_table :sample2 rescue nil
44
44
  end
45
45
  end
46
46
  assert_equal table_comment, result_table_comment
@@ -1,4 +1,4 @@
1
- require './test_helper'
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
2
  gem 'annotate'
3
3
  require 'annotate/annotate_models'
4
4
 
@@ -1,4 +1,4 @@
1
- require './test_helper'
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
2
 
3
3
  class Sample < ActiveRecord::Base
4
4
  self.table_name = 'sample'
@@ -6,13 +6,13 @@ postgres:
6
6
  password: postgres
7
7
 
8
8
  mysql:
9
- adapter: mysql # mysql2
9
+ adapter: mysql2
10
10
  database: migration_comments_test
11
11
  user: root
12
12
  password: password
13
13
 
14
14
  sqlite:
15
15
  adapter: sqlite3
16
- database: db/migration_comments_test
16
+ database: test/db/migration_comments_test
17
17
  pool: 5
18
18
  timeout: 5000
@@ -1,7 +1,8 @@
1
- require './test_helper'
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
2
 
3
3
  class SchemaDumperTest < Test::Unit::TestCase
4
4
  include TestHelper
5
+ include MigrationComments::SchemaFormatter
5
6
 
6
7
  def test_dump
7
8
  ActiveRecord::Schema.define do
@@ -14,23 +15,23 @@ class SchemaDumperTest < Test::Unit::TestCase
14
15
  dest.rewind
15
16
  result = dest.read
16
17
  expected = <<EOS
17
- ActiveRecord::Schema.define(:version => 1) do
18
+ ActiveRecord::Schema.define(#{render_kv_pair(:version, 1)}) do
18
19
 
19
- create_table "sample", :force => true, :comment => "a table comment" do |t|
20
- t.string "field1", :comment => "a \"comment\" \\ that ' needs; escaping''"
20
+ create_table "sample", #{render_kv_pair(:force, true)}, #{render_kv_pair(:comment, "a table comment")} do |t|
21
+ t.string "field1", __SPACES__#{render_kv_pair(:comment, %{a \"comment\" \\ that ' needs; escaping''})}
21
22
  t.integer "field2"
22
- t.string "field3", :default => "", :null => false, :comment => "third column comment"
23
+ t.string "field3", #{render_kv_pair(:default, "")}, #{render_kv_pair(:null, false)}, #{render_kv_pair(:comment, "third column comment")}
23
24
  end
24
25
 
25
26
  end
26
27
  EOS
27
-
28
- assert_match /#{Regexp.escape expected}/, result
28
+ assert_match /#{Regexp.escape(expected).gsub(/__SPACES__/, " +")}/, result
29
29
  end
30
30
 
31
31
  def test_dump_with_no_columns
32
32
  ActiveRecord::Schema.define do
33
- remove_column :sample, :field1, :field2
33
+ remove_column :sample, :field1
34
+ remove_column :sample, :field2
34
35
  set_table_comment :sample, "a table comment"
35
36
  end
36
37
  dest = StringIO.new
@@ -38,11 +39,38 @@ EOS
38
39
  dest.rewind
39
40
  result = dest.read
40
41
  expected = <<EOS
41
- ActiveRecord::Schema.define(:version => 1) do
42
+ ActiveRecord::Schema.define(#{render_kv_pair(:version, 1)}) do
42
43
 
43
- create_table "sample", :force => true, :comment => "a table comment" do |t|
44
+ create_table "sample", #{render_kv_pair(:force, true)}, #{render_kv_pair(:comment, "a table comment")} do |t|
44
45
  end
45
46
 
47
+ end
48
+ EOS
49
+
50
+ assert_match /#{Regexp.escape expected}/, result
51
+ end
52
+
53
+ def test_schema_dump_with_custom_type_error_for_pg
54
+ return unless ENV['DB'] == 'postgres'
55
+ ActiveRecord::Base.connection.execute "DROP TYPE IF EXISTS my_custom_type; CREATE TYPE my_custom_type AS ENUM('thing1', 'thing2');"
56
+ ActiveRecord::Base.connection.execute "ALTER TABLE sample ALTER COLUMN field2 TYPE my_custom_type USING 'thing1';"
57
+
58
+ ActiveRecord::Schema.define do
59
+ set_table_comment :sample, "a table comment"
60
+ set_column_comment :sample, :field1, "column comment"
61
+ end
62
+
63
+ dest = StringIO.new
64
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, dest)
65
+ dest.rewind
66
+ result = dest.read
67
+
68
+ expected = <<EOS
69
+ ActiveRecord::Schema.define(#{render_kv_pair(:version, 1)}) do
70
+
71
+ # Could not dump table "sample" because of following StandardError
72
+ # Unknown type 'my_custom_type' for column 'field2'
73
+
46
74
  end
47
75
  EOS
48
76
 
data/test/test_helper.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  require 'test/unit'
2
2
 
3
3
  require 'rubygems'
4
- gem 'rails', '>= 2.3.2'
4
+ gem 'activerecord', '>= 2.3.2'
5
5
  require 'active_record'
6
6
  require 'yaml'
7
7
 
8
- CONFIGURATIONS = YAML::load(IO.read('config/database.yml'))
8
+ CONFIGURATIONS = YAML::load(IO.read(File.join(File.dirname(__FILE__), 'config/database.yml')))
9
9
 
10
10
  ENV['DB'] ||= 'postgres' # override as needed
11
11
 
metadata CHANGED
@@ -1,79 +1,104 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: migration_comments
3
- version: !ruby/object:Gem::Version
4
- hash: 21
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 2
9
- - 1
10
- version: 0.2.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Pinny
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-12-31 00:00:00 -05:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- name: rails
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
12
+ date: 2013-07-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: !ruby/object:Gem::Requirement
25
17
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 7
30
- segments:
31
- - 2
32
- - 3
33
- - 2
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
34
21
  version: 2.3.2
35
22
  type: :runtime
36
- version_requirements: *id001
37
- - !ruby/object:Gem::Dependency
38
- name: annotate
39
23
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 2.3.2
30
+ - !ruby/object:Gem::Dependency
31
+ name: annotate
32
+ requirement: !ruby/object:Gem::Requirement
41
33
  none: false
42
- requirements:
34
+ requirements:
43
35
  - - ~>
44
- - !ruby/object:Gem::Version
45
- hash: 27
46
- segments:
47
- - 2
48
- - 5
49
- - 0
36
+ - !ruby/object:Gem::Version
50
37
  version: 2.5.0
51
38
  type: :development
52
- version_requirements: *id002
53
- - !ruby/object:Gem::Dependency
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 2.5.0
46
+ - !ruby/object:Gem::Dependency
54
47
  name: pg
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
55
  prerelease: false
56
- requirement: &id003 !ruby/object:Gem::Requirement
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: mysql2
64
+ requirement: !ruby/object:Gem::Requirement
57
65
  none: false
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- hash: 3
62
- segments:
63
- - 0
64
- version: "0"
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
65
70
  type: :development
66
- version_requirements: *id003
67
- description: Add schema comments in your migrations, see them in model annotations and db/schema.rb dump
68
- email:
69
- - pinny@medwiztech.com
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: sqlite3
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: Add schema comments in your migrations, see them in model annotations
95
+ and db/schema.rb dump
96
+ email:
97
+ - pinny@mwitz.com
70
98
  executables: []
71
-
72
99
  extensions: []
73
-
74
100
  extra_rdoc_files: []
75
-
76
- files:
101
+ files:
77
102
  - .gitignore
78
103
  - Gemfile
79
104
  - MIT-LICENSE
@@ -81,17 +106,22 @@ files:
81
106
  - Rakefile
82
107
  - lib/migration_comments.rb
83
108
  - lib/migration_comments/active_record/connection_adapters/abstract_adapter.rb
109
+ - lib/migration_comments/active_record/connection_adapters/abstract_adapter/schema_creation.rb
110
+ - lib/migration_comments/active_record/connection_adapters/abstract_sqlite_adapter.rb
111
+ - lib/migration_comments/active_record/connection_adapters/alter_table.rb
84
112
  - lib/migration_comments/active_record/connection_adapters/column.rb
85
113
  - lib/migration_comments/active_record/connection_adapters/column_definition.rb
86
114
  - lib/migration_comments/active_record/connection_adapters/comment_definition.rb
87
115
  - lib/migration_comments/active_record/connection_adapters/mysql2_adapter.rb
88
116
  - lib/migration_comments/active_record/connection_adapters/mysql_adapter.rb
89
117
  - lib/migration_comments/active_record/connection_adapters/postgresql_adapter.rb
118
+ - lib/migration_comments/active_record/connection_adapters/sqlite3_adapter.rb
90
119
  - lib/migration_comments/active_record/connection_adapters/sqlite_adapter.rb
91
120
  - lib/migration_comments/active_record/connection_adapters/table.rb
92
121
  - lib/migration_comments/active_record/connection_adapters/table_definition.rb
93
122
  - lib/migration_comments/active_record/schema_dumper.rb
94
123
  - lib/migration_comments/annotate_models.rb
124
+ - lib/migration_comments/schema_formatter.rb
95
125
  - lib/migration_comments/version.rb
96
126
  - migration_comments.gemspec
97
127
  - test/add_comments_test.rb
@@ -100,39 +130,34 @@ files:
100
130
  - test/config/database.yml
101
131
  - test/schema_dumper_test.rb
102
132
  - test/test_helper.rb
103
- has_rdoc: true
104
133
  homepage: https://github.com/pinnymz/migration_comments
105
134
  licenses: []
106
-
107
135
  post_install_message:
108
136
  rdoc_options: []
109
-
110
- require_paths:
137
+ require_paths:
111
138
  - lib
112
- required_ruby_version: !ruby/object:Gem::Requirement
139
+ required_ruby_version: !ruby/object:Gem::Requirement
113
140
  none: false
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- hash: 3
118
- segments:
141
+ requirements:
142
+ - - ! '>='
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ segments:
119
146
  - 0
120
- version: "0"
121
- required_rubygems_version: !ruby/object:Gem::Requirement
147
+ hash: 1998391628422785254
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
149
  none: false
123
- requirements:
124
- - - ">="
125
- - !ruby/object:Gem::Version
126
- hash: 3
127
- segments:
150
+ requirements:
151
+ - - ! '>='
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ segments:
128
155
  - 0
129
- version: "0"
156
+ hash: 1998391628422785254
130
157
  requirements: []
131
-
132
158
  rubyforge_project: migration_comments
133
- rubygems_version: 1.3.7
159
+ rubygems_version: 1.8.25
134
160
  signing_key:
135
161
  specification_version: 3
136
162
  summary: Comments for your migrations
137
163
  test_files: []
138
-