migration_comments 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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