migration_comments 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.travis.yml +27 -0
  4. data/README.rdoc +12 -3
  5. data/Rakefile +24 -0
  6. data/docker-compose.yml +12 -0
  7. data/gemfiles/rails4.gemfile +4 -0
  8. data/gemfiles/rails5.gemfile +4 -0
  9. data/lib/migration_comments.rb +12 -40
  10. data/lib/migration_comments/active_record/connection_adapters/abstract_adapter.rb +1 -10
  11. data/lib/migration_comments/active_record/connection_adapters/abstract_adapter/schema_creation.rb +22 -25
  12. data/lib/migration_comments/active_record/connection_adapters/alter_table.rb +5 -10
  13. data/lib/migration_comments/active_record/connection_adapters/column.rb +1 -5
  14. data/lib/migration_comments/active_record/connection_adapters/comment_definition.rb +1 -9
  15. data/lib/migration_comments/active_record/connection_adapters/mysql2_adapter.rb +97 -3
  16. data/lib/migration_comments/active_record/connection_adapters/postgresql_adapter.rb +19 -22
  17. data/lib/migration_comments/active_record/connection_adapters/sqlite3_adapter.rb +73 -46
  18. data/lib/migration_comments/active_record/connection_adapters/table.rb +3 -3
  19. data/lib/migration_comments/active_record/connection_adapters/table_definition.rb +9 -18
  20. data/lib/migration_comments/active_record/schema_dumper.rb +6 -10
  21. data/lib/migration_comments/annotate_models.rb +6 -8
  22. data/lib/migration_comments/schema_formatter.rb +8 -1
  23. data/lib/migration_comments/version.rb +1 -1
  24. data/migration_comments.gemspec +3 -10
  25. data/test/add_comments_test.rb +43 -2
  26. data/test/annotate_models_test.rb +6 -4
  27. data/test/auto_increment_test.rb +39 -9
  28. data/test/config/database.yml +2 -2
  29. data/test/primary_uuid_test.rb +27 -0
  30. data/test/schema_dumper_test.rb +35 -11
  31. data/test/test_helper.rb +8 -1
  32. metadata +34 -11
  33. data/lib/migration_comments/active_record/connection_adapters/abstract_sqlite_adapter.rb +0 -85
  34. data/lib/migration_comments/active_record/connection_adapters/mysql_adapter.rb +0 -107
  35. data/lib/migration_comments/active_record/connection_adapters/sqlite_adapter.rb +0 -71
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 766b7ebfb9c64bc9b8a4bc03e4c943d0276c6f49
4
- data.tar.gz: c33c766bd47e849dc07d5c5b454eddeb1ce3278c
3
+ metadata.gz: a92efc84724b53b99d1938f473c3fcdfb835968b
4
+ data.tar.gz: a782dfc206d8e690c70eecffe2a13e6c265ea1cb
5
5
  SHA512:
6
- metadata.gz: 5be5b935f97b70922631c45519bff6083fec3a9bc8fd6104c2f7f391aa888d0ac57fc413cb8a4ce3310eae1c15fa4bded524f9cc10a74ba20e5c1e85285a11a7
7
- data.tar.gz: 22b2a9ec4daaa59bf52b7a4c53969cb4d98340844857f564e9dda63d4ed598145cf052696e6529ac70c739f11db879587c378f2933b3ddb939a9db4faf1498f4
6
+ metadata.gz: c64821061f120a5013ea7244994a85b9cc90a2f8d3f0a1acfa7933a42dcce44c31b06c6f31d872d9db874393215f5444954567a37781ba1c2c182531c0b09c52
7
+ data.tar.gz: 8b0a8d93451ac641c7090ba406bb9f24762f0afcd8501751274ac33d2be99c91257112cb7f8bf17107737bf50a39697ff3d8ee13e0e6177aa1bc980f56c39f42
data/.gitignore CHANGED
@@ -3,4 +3,5 @@
3
3
  Gemfile.lock
4
4
  pkg/*
5
5
  .idea/*
6
- test/db/migration_comments_test
6
+ test/db/migration_comments_test
7
+ .byebug_history
data/.travis.yml ADDED
@@ -0,0 +1,27 @@
1
+ sudo: required
2
+ language: ruby
3
+ rvm:
4
+ - 2.1.8
5
+ - 2.2.4
6
+ - 2.3.0
7
+ gemfile:
8
+ - Gemfile
9
+ - gemfiles/rails4.gemfile
10
+ - gemfiles/rails5.gemfile
11
+ services:
12
+ - mysql
13
+ - postgresql
14
+ before_install:
15
+ - gem install bundler
16
+ before_script:
17
+ - mysql -u root -e "create database migration_comments_test;"
18
+ - psql -U postgres -c "ALTER USER "postgres" WITH PASSWORD 'password';"
19
+ - PGPASSWORD=password psql -U postgres -c "create database migration_comments_test;"
20
+ env:
21
+ - DB=postgres
22
+ - DB=mysql
23
+ - DB=sqlite
24
+ matrix:
25
+ exclude:
26
+ - rvm: 2.1.8
27
+ gemfile: gemfiles/rails5.gemfile
data/README.rdoc CHANGED
@@ -4,9 +4,18 @@ Comments for your migrations
4
4
 
5
5
  Tested on:
6
6
 
7
- ActiveRecord 4.x:: using Ruby 1.9.3 / 2.0
8
- ActiveRecord 3.x:: using Ruby 1.8.7 / 1.9.x / 2.0
9
- ActiveRecord 2.3.x (deprecated):: using Ruby 1.8.6 / 1.8.7
7
+ ActiveRecord 5.0:: Using Ruby 2.2 and higher
8
+ ActiveRecord 4.2:: using Ruby 2.1 and higher
9
+
10
+ Status: {<img src="https://travis-ci.org/pinnymz/migration_comments.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/pinnymz/migration_comments]
11
+
12
+ == **IMPORTANT UPDATE**
13
+
14
+ ActiveRecord 5.0 is introducing baked-in comment support, although not all features provided by this project have yet been completely implemented.
15
+ This is expected to be rectified by ActiveRecord 5.1, and as such ActiveRecord 5.0 will likely be the last version for which this gem will work (or be needed).
16
+ ActiveRecord 5.0 itself will be supported by this project, but many features are overlapping and you may find that you won't need it at all.
17
+
18
+ For those using a version of ActiveRecord prior to 4.2 or of Ruby prior to 2.1, please use the v0.3.2 version of the gem.
10
19
 
11
20
  == Why?
12
21
 
data/Rakefile CHANGED
@@ -1,8 +1,32 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
3
 
4
+ task :default => [:test]
5
+
4
6
  Rake::TestTask.new do |t|
5
7
  t.libs << "test"
6
8
  t.test_files = FileList['test/*_test.rb']
7
9
  t.verbose = true
8
10
  end
11
+
12
+ namespace :test do
13
+ task all: [:postgres, :mysql, :sqlite]
14
+
15
+ task :postgres do
16
+ ENV['DB'] = 'postgres'
17
+ puts "\n\nrunning PostgreSQL tests..."
18
+ Rake::Task['test'].execute
19
+ end
20
+
21
+ task :mysql do
22
+ ENV['DB'] = 'mysql'
23
+ puts "\n\nrunning MySQL tests..."
24
+ Rake::Task['test'].execute
25
+ end
26
+
27
+ task :sqlite do
28
+ ENV['DB'] = 'sqlite'
29
+ puts "\n\nrunning SQLite tests..."
30
+ Rake::Task['test'].execute
31
+ end
32
+ end
@@ -0,0 +1,12 @@
1
+ mysql:
2
+ image: "mysql:5.6"
3
+ ports:
4
+ - "3306:3306"
5
+ environment:
6
+ MYSQL_ROOT_PASSWORD: password
7
+ postgres:
8
+ image: "postgres:9.4"
9
+ ports:
10
+ - "5432:5432"
11
+ environment:
12
+ POSTGRES_PASSWORD: postgres
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+ gem "activerecord", '~> 4.0'
3
+
4
+ gemspec :path => '../'
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+ gem "activerecord", '~> 5.0.0.rc1'
3
+
4
+ gemspec :path => '../'
@@ -10,76 +10,48 @@ require 'migration_comments/active_record/connection_adapters/table_definition'
10
10
  require 'migration_comments/active_record/connection_adapters/alter_table'
11
11
  require 'migration_comments/active_record/connection_adapters/abstract_adapter'
12
12
  require 'migration_comments/active_record/connection_adapters/abstract_adapter/schema_creation'
13
- require 'migration_comments/active_record/connection_adapters/mysql_adapter'
14
13
  require 'migration_comments/active_record/connection_adapters/mysql2_adapter'
15
14
  require 'migration_comments/active_record/connection_adapters/postgresql_adapter'
16
- require 'migration_comments/active_record/connection_adapters/abstract_sqlite_adapter'
17
- require 'migration_comments/active_record/connection_adapters/sqlite_adapter'
18
15
  require 'migration_comments/active_record/connection_adapters/sqlite3_adapter'
19
16
 
20
- require 'active_record/connection_adapters/abstract_adapter'
21
-
22
17
  module MigrationComments
23
18
  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
20
  base_names = %w(SchemaDumper) +
29
- %w(ColumnDefinition Column Table TableDefinition AbstractAdapter).map{|name| "ConnectionAdapters::#{name}"}
21
+ %w(AbstractAdapter AbstractAdapter::SchemaCreation AlterTable ColumnDefinition Column Table TableDefinition).map{|name| "ConnectionAdapters::#{name}"}
30
22
 
31
23
  base_names.each do |base_name|
32
24
  ar_class = "ActiveRecord::#{base_name}".constantize
33
25
  mc_class = "MigrationComments::ActiveRecord::#{base_name}".constantize
34
- unless ar_class.ancestors.include?(mc_class)
35
- ar_class.__send__(:include, mc_class)
36
- end
37
- end
38
-
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
26
+ unless ar_class.descendants.include?(mc_class)
27
+ ar_class.prepend mc_class
51
28
  end
52
29
  end
53
30
 
54
- adapters = %w(PostgreSQL Mysql Mysql2)
55
- adapters << (::ActiveRecord::VERSION::MAJOR <= 3 ? "SQLite" : "SQLite3")
31
+ adapters = %w(PostgreSQL Mysql2 SQLite3)
56
32
  adapters.each do |adapter|
57
33
  begin
58
34
  require("active_record/connection_adapters/#{adapter.downcase}_adapter")
59
35
  adapter_class = ('::ActiveRecord::ConnectionAdapters::' << "#{adapter}Adapter").constantize
60
36
  mc_class = ('MigrationComments::ActiveRecord::ConnectionAdapters::' << "#{adapter}Adapter").constantize
61
- adapter_class.module_eval do
62
- adapter_class.__send__(:include, mc_class)
37
+ unless adapter_class.descendants.include?(mc_class)
38
+ adapter_class.prepend mc_class
63
39
  end
64
- rescue Exception => ex
40
+ rescue
65
41
  end
66
42
  end
67
43
 
68
44
  # annotations are not required for this gem, but if they exist they should be updated
69
45
  begin
70
- begin # first try to load from the 'annotate' gem
71
- require 'annotate/annotate_models'
72
- rescue Exception => ex
73
- # continue as it may be already accessible through a plugin
74
- end
75
- gem_class = AnnotateModels
76
- # don't require this until after the original AnnotateModels loads to avoid namespace confusion
46
+ require 'annotate/annotate_models'
47
+ gem_class = ::AnnotateModels
77
48
  require 'migration_comments/annotate_models'
78
49
  mc_class = MigrationComments::AnnotateModels
79
50
  unless gem_class.ancestors.include?(mc_class)
80
- gem_class.__send__(:include, mc_class)
51
+ gem_class.prepend mc_class
81
52
  end
82
- rescue Exception => ex
53
+ rescue
54
+ debugger
83
55
  # if we got here, don't bother installing comments into annotations
84
56
  end
85
57
  end
@@ -6,15 +6,6 @@ module MigrationComments::ActiveRecord::ConnectionAdapters
6
6
  def set_column_comment(table_name, column_name, comment_text)
7
7
  end
8
8
 
9
- def add_table_comment(*args)
10
- puts "'add_table_comment' is deprecated, and will be removed in future releases. Use 'set_table_comment' instead."
11
- set_table_comment(*args)
12
- end
13
- def add_column_comment(*args)
14
- puts "'add_column_comment' is deprecated, and will be removed in future releases. Use 'set_column_comment' instead."
15
- set_column_comment(*args)
16
- end
17
-
18
9
  def comments_supported?
19
10
  false
20
11
  end
@@ -24,7 +15,7 @@ module MigrationComments::ActiveRecord::ConnectionAdapters
24
15
  false
25
16
  end
26
17
 
27
- # PostgreSQL style - comment specific commands
18
+ # PostgreSQL style - comment-specific commands
28
19
  def independent_comments?
29
20
  false
30
21
  end
@@ -1,48 +1,45 @@
1
1
  module MigrationComments::ActiveRecord::ConnectionAdapters::AbstractAdapter
2
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 :add_column_options!, :migration_comments
7
- alias_method_chain :visit_TableDefinition, :migration_comments
8
- alias_method_chain :visit_ColumnDefinition, :migration_comments
9
- end
10
- end
11
-
12
- def column_options_with_migration_comments(o)
13
- column_options = o.primary_key? ? {} : column_options_without_migration_comments(o)
14
- column_options[:comment] = o.comment.comment_text if o.comment
3
+ def column_options(o)
4
+ column_options = super(o)
5
+ column_options[:comment] = o.comment.comment_text if o.comment.respond_to?(:comment_text)
15
6
  column_options
16
7
  end
17
8
 
18
- def add_column_options_with_migration_comments!(sql, options)
19
- sql = add_column_options_without_migration_comments!(sql, options)
9
+ def add_column_options!(sql, options)
10
+ sql = super(sql, options)
20
11
  if options.keys.include?(:comment) && !@conn.independent_comments?
21
- sql << MigrationComments::ActiveRecord::ConnectionAdapters::CommentDefinition.new(@conn, nil, nil, options[:comment]).to_sql
12
+ comment_definition = MigrationComments::ActiveRecord::ConnectionAdapters::CommentDefinition.new(nil, nil, options[:comment])
13
+ sql << @conn.comment_sql(comment_definition)
22
14
  end
23
15
  sql
24
16
  end
25
17
 
26
- def visit_TableDefinition_with_migration_comments(o)
18
+ def visit_TableDefinition(o)
27
19
  if @conn.inline_comments?
28
20
  create_sql = "CREATE#{' TEMPORARY' if o.temporary} TABLE "
29
- create_sql << "#{quote_table_name(o.name)}#{o.table_comment} ("
21
+ create_sql << "#{quote_table_name(o.name)}#{@conn.comment_sql(o.comment)} ("
30
22
  create_sql << o.columns.map { |c| accept c }.join(', ')
31
23
  create_sql << ") #{o.options}"
32
24
  create_sql
33
25
  else
34
- visit_TableDefinition_without_migration_comments(o)
26
+ super(o)
35
27
  end
36
28
  end
37
29
 
38
- def visit_ColumnDefinition_with_migration_comments(o)
39
- if @conn.inline_comments?
40
- sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
41
- column_sql = "#{quote_column_name(o.name)} #{sql_type}"
42
- add_column_options!(column_sql, column_options(o))
43
- column_sql
30
+ def visit_ColumnDefinition(o)
31
+ if @conn.inline_comments? && o.type.to_sym == :primary_key && o.comment
32
+ if ::ActiveRecord::VERSION::MAJOR >= 5
33
+ comment_sql = super(o)
34
+ comment_sql << @conn.comment_sql(o.comment)
35
+ else
36
+ sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
37
+ column_sql = "#{quote_column_name(o.name)} #{sql_type}"
38
+ add_column_options!(column_sql, column_options(o))
39
+ column_sql
40
+ end
44
41
  else
45
- visit_ColumnDefinition_without_migration_comments(o)
42
+ super(o)
46
43
  end
47
44
  end
48
45
  end
@@ -1,16 +1,11 @@
1
1
  module MigrationComments::ActiveRecord::ConnectionAdapters
2
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)
3
+ def add_column(name, type, options)
4
+ super(name, type, options)
11
5
  if options.keys.include?(:comment)
12
- column = @adds.last
13
- column.comment = CommentDefinition.new(nil, @td, name, options[:comment])
6
+ added_entity = @adds.last
7
+ column = added_entity.respond_to?(:column) ? added_entity.column : added_entity
8
+ column.comment = CommentDefinition.new(@td, name, options[:comment])
14
9
  end
15
10
  end
16
11
  end
@@ -1,9 +1,5 @@
1
1
  module MigrationComments::ActiveRecord::ConnectionAdapters
2
2
  module Column
3
- def self.included(base)
4
- base.class_eval do
5
- attr_accessor :comment
6
- end
7
- end
3
+ attr_accessor :comment
8
4
  end
9
5
  end
@@ -1,22 +1,14 @@
1
1
  module MigrationComments::ActiveRecord::ConnectionAdapters
2
- class CommentDefinition < Struct.new(:adapter, :table, :column_name, :comment_text)
2
+ class CommentDefinition < Struct.new(:table_name, :column_name, :comment_text)
3
3
  def to_dump
4
4
  table_comment? ?
5
5
  "set_table_comment :#{table_name}, %{#{comment_text}}" :
6
6
  "set_column_comment :#{table_name}, :#{column_name}, %{#{comment_text}}"
7
7
  end
8
8
 
9
- def to_sql
10
- adapter.comment_sql(self)
11
- end
12
- alias to_s :to_sql
13
-
14
9
  def table_comment?
15
10
  column_name.blank?
16
11
  end
17
12
 
18
- def table_name
19
- table.respond_to?(:name) ? table.name : table
20
- end
21
13
  end
22
14
  end
@@ -1,9 +1,103 @@
1
1
  module MigrationComments::ActiveRecord::ConnectionAdapters
2
2
  module Mysql2Adapter
3
- def self.included(base)
4
- base.class_eval do
5
- include MigrationComments::ActiveRecord::ConnectionAdapters::MysqlAdapter
3
+
4
+ def comments_supported?
5
+ true
6
+ end
7
+
8
+ def set_table_comment(table_name, comment_text)
9
+ execute "ALTER TABLE #{quote_table_name table_name} COMMENT #{escaped_comment(comment_text)}"
10
+ end
11
+
12
+ def set_column_comment(table_name, column_name, comment_text)
13
+ column = column_for(table_name, column_name)
14
+ options = {
15
+ comment: comment_text,
16
+ auto_increment: !!(column.extra =~ /auto_increment/) # MySQL adapter drops this on calls to change_column
17
+ }
18
+ change_column table_name, column_name, column.sql_type, options
19
+ end
20
+
21
+ if ::ActiveRecord::VERSION::MAJOR >= 5
22
+ def add_sql_comment!(sql, comment)
23
+ comment_text = comment.respond_to?(:comment_text) ? comment.comment_text : comment
24
+ super(sql, comment_text)
25
+ end
26
+ end
27
+
28
+ def retrieve_table_comment(table_name)
29
+ select_value(table_comment_sql(table_name)).presence
30
+ end
31
+
32
+ def retrieve_column_comments(table_name, *column_names)
33
+ result = select_rows(column_comment_sql(table_name, *column_names)) || []
34
+ Hash[result.map{|row| [row[0].to_sym, row[1].presence]}]
35
+ end
36
+
37
+ def create_table(table_name, options={})
38
+ local_table_definition = nil
39
+ super(table_name, options) do |td|
40
+ local_table_definition = td
41
+ local_table_definition.comment = options[:comment] if options.has_key?(:comment)
42
+ yield td if block_given?
43
+ end
44
+ comments = local_table_definition.collect_comments(table_name)
45
+ comments.each do |comment_definition|
46
+ execute_comment comment_definition
47
+ end
48
+ end
49
+
50
+ def change_column(table_name, column_name, type, options={})
51
+ unless options.keys.include?(:comment)
52
+ options.merge!(:comment => retrieve_column_comment(table_name, column_name))
6
53
  end
54
+ super(table_name, column_name, type, options)
55
+ end
56
+
57
+ def add_column_options!(sql, options)
58
+ super(sql, options)
59
+ if options.keys.include?(:comment)
60
+ sql << comment_sql(CommentDefinition.new(nil, nil, options[:comment]))
61
+ end
62
+ end
63
+
64
+ def comment_sql(comment_definition)
65
+ " COMMENT #{escaped_comment(comment_definition.comment_text)}"
66
+ end
67
+
68
+ def execute_comment(comment_definition)
69
+ if comment_definition.table_comment?
70
+ set_table_comment comment_definition.table_name, comment_definition.comment_text
71
+ else
72
+ set_column_comment comment_definition.table_name, comment_definition.column_name, comment_definition.comment_text
73
+ end
74
+ end
75
+
76
+ private
77
+ def escaped_comment(comment)
78
+ comment.nil? ? "''" : "'#{comment.gsub("'", "''").gsub("\\", "\\\\\\\\")}'"
79
+ end
80
+
81
+ def table_comment_sql(table_name)
82
+ <<SQL
83
+ SELECT table_comment FROM INFORMATION_SCHEMA.TABLES
84
+ WHERE table_schema = '#{database_name}'
85
+ AND table_name = '#{table_name}'
86
+ SQL
87
+ end
88
+
89
+ def column_comment_sql(table_name, *column_names)
90
+ col_matcher_sql = " AND column_name IN (#{column_names.map{|c_name| "'#{c_name}'"}.join(',')})" unless column_names.empty?
91
+ <<SQL
92
+ SELECT column_name, column_comment FROM INFORMATION_SCHEMA.COLUMNS
93
+ WHERE table_schema = '#{database_name}'
94
+ AND table_name = '#{table_name}' #{col_matcher_sql}
95
+ SQL
96
+ end
97
+
98
+ def database_name
99
+ @database_name ||= select_value("SELECT DATABASE()")
7
100
  end
101
+
8
102
  end
9
103
  end