schema_plus 1.8.9 → 2.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -4
- data/.travis.yml +1 -47
- data/CHANGELOG.md +0 -35
- data/README.md +73 -107
- data/Rakefile +7 -10
- data/TODO.md +51 -0
- data/gemfiles/Gemfile.base +2 -0
- data/lib/schema_column_plus.rb +7 -0
- data/lib/{schema_plus → schema_column_plus}/active_record/connection_adapters/column.rb +13 -11
- data/lib/schema_column_plus/middleware/model.rb +22 -0
- data/lib/schema_db_default.rb +13 -0
- data/lib/{schema_plus → schema_db_default}/active_record/attribute.rb +4 -4
- data/lib/schema_db_default/db_default.rb +17 -0
- data/lib/schema_db_default/middleware.rb +30 -0
- data/lib/schema_default_expr.rb +32 -0
- data/lib/schema_default_expr/active_record/connection_adapters/mysql_adapter.rb +17 -0
- data/lib/schema_default_expr/active_record/connection_adapters/postgresql_adapter.rb +18 -0
- data/lib/schema_default_expr/active_record/connection_adapters/sqlite3_adapter.rb +35 -0
- data/lib/schema_default_expr/middleware.rb +54 -0
- data/lib/schema_pg_enums.rb +6 -0
- data/lib/schema_pg_enums/active_record.rb +69 -0
- data/lib/schema_pg_enums/middleware.rb +23 -0
- data/lib/schema_plus.rb +17 -45
- data/lib/schema_plus/active_record/base.rb +6 -23
- data/lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb +80 -181
- data/lib/schema_plus/active_record/connection_adapters/foreign_key_definition.rb +78 -99
- data/lib/schema_plus/active_record/connection_adapters/mysql_adapter.rb +34 -114
- data/lib/schema_plus/active_record/connection_adapters/postgresql_adapter.rb +16 -370
- data/lib/schema_plus/active_record/connection_adapters/schema_statements.rb +1 -67
- data/lib/schema_plus/active_record/connection_adapters/sqlite3_adapter.rb +18 -112
- data/lib/schema_plus/active_record/connection_adapters/table_definition.rb +14 -116
- data/lib/schema_plus/active_record/migration/command_recorder.rb +8 -59
- data/lib/schema_plus/middleware/dumper.rb +94 -0
- data/lib/schema_plus/middleware/migration.rb +167 -0
- data/lib/schema_plus/middleware/model.rb +17 -0
- data/lib/schema_plus/version.rb +1 -1
- data/lib/schema_plus_tables.rb +15 -0
- data/lib/schema_plus_tables/active_record/connection_adapters/abstract_adapter.rb +20 -0
- data/lib/schema_plus_tables/active_record/connection_adapters/mysql_adapter.rb +25 -0
- data/lib/schema_plus_tables/active_record/connection_adapters/postgresql_adapter.rb +13 -0
- data/lib/schema_plus_tables/active_record/connection_adapters/sqlite3_adapter.rb +12 -0
- data/lib/schema_views.rb +16 -0
- data/lib/schema_views/active_record/connection_adapters/abstract_adapter.rb +41 -0
- data/lib/schema_views/active_record/connection_adapters/mysql_adapter.rb +30 -0
- data/lib/schema_views/active_record/connection_adapters/postgresql_adapter.rb +31 -0
- data/lib/schema_views/active_record/connection_adapters/sqlite3_adapter.rb +18 -0
- data/lib/schema_views/middleware.rb +47 -0
- data/schema_dev.yml +1 -31
- data/schema_plus.gemspec +11 -9
- data/spec/foreign_key_definition_spec.rb +7 -7
- data/spec/foreign_key_spec.rb +63 -48
- data/spec/migration_spec.rb +58 -203
- data/spec/named_schemas_spec.rb +5 -88
- data/spec/{column_spec.rb → schema_column_plus/column_spec.rb} +26 -48
- data/spec/schema_db_default/column_spec.rb +58 -0
- data/spec/{column_default_spec.rb → schema_default_expr/column_default_spec.rb} +1 -2
- data/spec/schema_default_expr/schema_dumper_spec.rb +116 -0
- data/spec/schema_dumper_spec.rb +22 -327
- data/spec/{enum_spec.rb → schema_pg_enums/enum_spec.rb} +1 -1
- data/spec/schema_pg_enums/schema_dumper_spec.rb +37 -0
- data/spec/schema_views/named_schemas_spec.rb +97 -0
- data/spec/{views_spec.rb → schema_views/views_spec.rb} +1 -1
- data/spec/spec_helper.rb +2 -1
- data/spec/support/matchers/reference.rb +11 -12
- metadata +104 -57
- data/gemfiles/rails-3.2/Gemfile.base +0 -3
- data/gemfiles/rails-3.2/Gemfile.mysql +0 -10
- data/gemfiles/rails-3.2/Gemfile.mysql2 +0 -10
- data/gemfiles/rails-3.2/Gemfile.postgresql +0 -10
- data/gemfiles/rails-3.2/Gemfile.sqlite3 +0 -10
- data/gemfiles/rails-4.0/Gemfile.base +0 -3
- data/gemfiles/rails-4.0/Gemfile.mysql2 +0 -10
- data/gemfiles/rails-4.0/Gemfile.postgresql +0 -10
- data/gemfiles/rails-4.0/Gemfile.sqlite3 +0 -10
- data/gemfiles/rails-4.1/Gemfile.base +0 -3
- data/gemfiles/rails-4.1/Gemfile.mysql2 +0 -10
- data/gemfiles/rails-4.1/Gemfile.postgresql +0 -10
- data/gemfiles/rails-4.1/Gemfile.sqlite3 +0 -10
- data/lib/schema_plus/active_record/column_options_handler.rb +0 -117
- data/lib/schema_plus/active_record/connection_adapters/index_definition.rb +0 -70
- data/lib/schema_plus/active_record/db_default.rb +0 -19
- data/lib/schema_plus/active_record/foreign_keys.rb +0 -137
- data/lib/schema_plus/active_record/schema_dumper.rb +0 -171
- data/lib/schema_plus/railtie.rb +0 -20
- data/spec/index_definition_spec.rb +0 -211
- data/spec/index_spec.rb +0 -249
@@ -4,18 +4,9 @@ module SchemaPlus::ActiveRecord::ConnectionAdapters
|
|
4
4
|
def self.included(base) #:nodoc:
|
5
5
|
base.class_eval do
|
6
6
|
alias_method_chain :create_table, :schema_plus
|
7
|
-
alias_method_chain :add_reference, :schema_plus unless ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
8
|
-
alias_method_chain :add_index_options, :schema_plus if "#{::ActiveRecord::VERSION::MAJOR}.#{::ActiveRecord::VERSION::MINOR}".to_r >= "4.2".to_r
|
9
|
-
include AddIndex
|
10
7
|
end
|
11
8
|
end
|
12
9
|
|
13
|
-
def add_reference_with_schema_plus(table_name, ref_name, options = {}) #:nodoc:
|
14
|
-
options[:references] = nil if options[:polymorphic]
|
15
|
-
options[:_index] = options.delete(:index) unless options[:polymorphic] # usurp index creation from AR
|
16
|
-
add_reference_without_schema_plus(table_name, ref_name, options)
|
17
|
-
end
|
18
|
-
|
19
10
|
##
|
20
11
|
# :method: create_table
|
21
12
|
#
|
@@ -33,68 +24,11 @@ module SchemaPlus::ActiveRecord::ConnectionAdapters
|
|
33
24
|
# override rails' :force to cascade
|
34
25
|
drop_table(table, if_exists: true, cascade: true) if options.delete(:force)
|
35
26
|
|
36
|
-
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
37
|
-
indexes = []
|
38
|
-
end
|
39
27
|
create_table_without_schema_plus(table, options) do |table_definition|
|
40
28
|
table_definition.schema_plus_config = SchemaPlus.config.merge(config_options)
|
41
|
-
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
42
|
-
table_definition.name = table
|
43
|
-
end
|
44
29
|
yield table_definition if block_given?
|
45
|
-
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
46
|
-
indexes = table_definition.indexes
|
47
|
-
end
|
48
|
-
end
|
49
|
-
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
50
|
-
indexes.each do |index|
|
51
|
-
add_index(table, index.columns, index.opts)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def add_index_options_with_schema_plus(table_name, column_name, options = {})
|
57
|
-
options = options.dup
|
58
|
-
with_columns = options.delete(:with) { |_| [] }
|
59
|
-
add_index_options_without_schema_plus(table_name, Array(column_name).concat(Array(with_columns).map(&:to_s)), options)
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.add_index_exception_handler(connection, table, columns, options, e) #:nodoc:
|
63
|
-
raise unless e.message.match(/["']([^"']+)["'].*already exists/)
|
64
|
-
name = $1
|
65
|
-
existing = connection.indexes(table).find{|i| i.name == name}
|
66
|
-
attempted = ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table, columns, options.merge(:name => name))
|
67
|
-
raise if attempted != existing
|
68
|
-
::ActiveRecord::Base.logger.warn "[schema_plus] Index name #{name.inspect}' on table #{table.inspect} already exists. Skipping."
|
69
|
-
end
|
70
|
-
|
71
|
-
module AddIndex
|
72
|
-
def self.included(base) #:nodoc:
|
73
|
-
base.class_eval do
|
74
|
-
alias_method_chain :add_index, :schema_plus
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
##
|
79
|
-
# :method: add_index
|
80
|
-
#
|
81
|
-
# SchemaPlus modifies SchemaStatements::add_index so that it ignores
|
82
|
-
# errors raised about add an index that already exists -- i.e. that has
|
83
|
-
# the same index name, same columns, and same options -- and writes a
|
84
|
-
# warning to the log. Some combinations of rails & DB adapter versions
|
85
|
-
# would log such a warning, others would raise an error; with
|
86
|
-
# SchemaPlus all versions log the warning and do not raise the error.
|
87
|
-
#
|
88
|
-
# (This avoids collisions between SchemaPlus's auto index behavior and
|
89
|
-
# legacy explicit add_index statements, for platforms that would raise
|
90
|
-
# an error.)
|
91
|
-
#
|
92
|
-
def add_index_with_schema_plus(table, columns, options={})
|
93
|
-
options.delete(:if_exists) if options # some callers explcitly pass options=nil
|
94
|
-
add_index_without_schema_plus(table, columns, options)
|
95
|
-
rescue => e
|
96
|
-
SchemaStatements.add_index_exception_handler(self, table, columns, options, e)
|
97
30
|
end
|
98
31
|
end
|
99
32
|
end
|
33
|
+
|
100
34
|
end
|
@@ -1,24 +1,6 @@
|
|
1
1
|
module SchemaPlus
|
2
2
|
module ActiveRecord
|
3
3
|
module ConnectionAdapters
|
4
|
-
module SQLiteColumn
|
5
|
-
def initialize(name, default, sql_type = nil, null = true)
|
6
|
-
if default =~ /DATETIME/
|
7
|
-
@default_expr = "(#{default})"
|
8
|
-
end
|
9
|
-
super(name, default, sql_type, null)
|
10
|
-
end
|
11
|
-
|
12
|
-
# AR 4.2 uses default_function rather than default_expr
|
13
|
-
def self.included(base)
|
14
|
-
base.alias_method_chain :default_function, :sqlite3 if base.instance_methods.include? :default_function
|
15
|
-
end
|
16
|
-
|
17
|
-
def default_function_with_sqlite3
|
18
|
-
@default_function ||= "(#{default})" if default =~ /DATETIME/
|
19
|
-
default_function_without_sqlite3
|
20
|
-
end
|
21
|
-
end
|
22
4
|
|
23
5
|
# SchemaPlus includes an Sqlite3 implementation of the AbstractAdapter
|
24
6
|
# extensions.
|
@@ -28,18 +10,7 @@ module SchemaPlus
|
|
28
10
|
|
29
11
|
def self.included(base)
|
30
12
|
base.class_eval do
|
31
|
-
alias_method_chain :indexes, :schema_plus
|
32
13
|
alias_method_chain :rename_table, :schema_plus
|
33
|
-
alias_method_chain :tables, :schema_plus
|
34
|
-
alias_method_chain :copy_table, :schema_plus
|
35
|
-
end
|
36
|
-
|
37
|
-
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
38
|
-
::ActiveRecord::ConnectionAdapters::SQLiteColumn.send(:include, SQLiteColumn) unless ::ActiveRecord::ConnectionAdapters::SQLiteColumn.include?(SQLiteColumn)
|
39
|
-
elsif defined? ::ActiveRecord::ConnectionAdapters::SQLite3Column
|
40
|
-
::ActiveRecord::ConnectionAdapters::SQLite3Column.send(:include, SQLiteColumn) unless ::ActiveRecord::ConnectionAdapters::SQLite3Column.include?(SQLiteColumn)
|
41
|
-
else # in ActiveRecord::VERSION 4.2 there's no SQLite3Column
|
42
|
-
::ActiveRecord::ConnectionAdapters::Column.send(:include, SQLiteColumn) unless ::ActiveRecord::ConnectionAdapters::Column.include?(SQLiteColumn)
|
43
14
|
end
|
44
15
|
end
|
45
16
|
|
@@ -48,57 +19,17 @@ module SchemaPlus
|
|
48
19
|
execute('PRAGMA FOREIGN_KEYS = ON')
|
49
20
|
end
|
50
21
|
|
51
|
-
def supports_partial_indexes? #:nodoc:
|
52
|
-
# unfortunately with the current setup there's no easy way to
|
53
|
-
# test multiple SQLite3 versions. Currently travis-ci uses
|
54
|
-
# SQLite3 version 3.7 but local development on OS X uses 3.8.
|
55
|
-
SQLite3.libversion >= 3008000
|
56
|
-
end
|
57
|
-
|
58
|
-
def indexes_with_schema_plus(table_name, name = nil)
|
59
|
-
indexes = indexes_without_schema_plus(table_name, name)
|
60
|
-
exec_query("SELECT name, sql FROM sqlite_master WHERE type = 'index'").map do |row|
|
61
|
-
sql = row['sql']
|
62
|
-
index = nil
|
63
|
-
getindex = -> { index ||= indexes.detect { |i| i.name == row['name'] } }
|
64
|
-
if (desc_columns = sql.scan(/['"`]?(\w+)['"`]? DESC\b/).flatten).any?
|
65
|
-
getindex.call()
|
66
|
-
index.orders = Hash[index.columns.map {|column| [column, desc_columns.include?(column) ? :desc : :asc]}]
|
67
|
-
end
|
68
|
-
if (conditions = sql.match(/\bWHERE\s+(.*)/i))
|
69
|
-
getindex.call()
|
70
|
-
index.conditions = conditions[1]
|
71
|
-
end
|
72
|
-
end
|
73
|
-
indexes
|
74
|
-
end
|
75
|
-
|
76
|
-
def copy_table_with_schema_plus(*args, &block)
|
77
|
-
fk_override = { :auto_create => false, :auto_index => false }
|
78
|
-
save = Hash[fk_override.keys.collect{|key| [key, SchemaPlus.config.foreign_keys.send(key)]}]
|
79
|
-
begin
|
80
|
-
SchemaPlus.config.foreign_keys.update_attributes(fk_override)
|
81
|
-
copy_table_without_schema_plus(*args, &block)
|
82
|
-
ensure
|
83
|
-
SchemaPlus.config.foreign_keys.update_attributes(save)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
22
|
def rename_table_with_schema_plus(oldname, newname) #:nodoc:
|
88
23
|
rename_table_without_schema_plus(oldname, newname)
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
def add_foreign_key(table_name, column_names, references_table_name, references_column_names, options = {})
|
93
|
-
raise NotImplementedError, "Sqlite3 does not support altering a table to add foreign key constraints (table #{table_name.inspect} column #{column_names.inspect})"
|
24
|
+
rename_foreign_keys(oldname, newname)
|
94
25
|
end
|
95
26
|
|
96
|
-
def
|
97
|
-
raise NotImplementedError, "Sqlite3 does not support altering a table to
|
27
|
+
def add_foreign_key(table_name, to_table, options = {})
|
28
|
+
raise NotImplementedError, "Sqlite3 does not support altering a table to add foreign key constraints (table #{table_name.inspect} to #{to_table.inspect})"
|
98
29
|
end
|
99
30
|
|
100
|
-
def
|
101
|
-
|
31
|
+
def remove_foreign_key(table_name, *args)
|
32
|
+
raise NotImplementedError, "Sqlite3 does not support altering a table to remove foreign key constraints (table #{table_name.inspect} constraint #{args.inspect})"
|
102
33
|
end
|
103
34
|
|
104
35
|
def foreign_keys(table_name, name = nil)
|
@@ -106,21 +37,7 @@ module SchemaPlus
|
|
106
37
|
end
|
107
38
|
|
108
39
|
def reverse_foreign_keys(table_name, name = nil)
|
109
|
-
get_foreign_keys(nil, name).select{|definition| definition.
|
110
|
-
end
|
111
|
-
|
112
|
-
def tables_with_schema_plus(*args)
|
113
|
-
# AR 4.2 explicitly looks for views or tables, but only for sqlite3. so take away the tables.
|
114
|
-
tables_without_schema_plus(*args) - views
|
115
|
-
end
|
116
|
-
|
117
|
-
def views(name = nil)
|
118
|
-
execute("SELECT name FROM sqlite_master WHERE type='view'", name).collect{|row| row["name"]}
|
119
|
-
end
|
120
|
-
|
121
|
-
def view_definition(view_name, name = nil)
|
122
|
-
sql = execute("SELECT sql FROM sqlite_master WHERE type='view' AND name=#{quote(view_name)}", name).collect{|row| row["sql"]}.first
|
123
|
-
sql.sub(/^CREATE VIEW \S* AS\s+/im, '') unless sql.nil?
|
40
|
+
get_foreign_keys(nil, name).select{|definition| definition.to_table == table_name}
|
124
41
|
end
|
125
42
|
|
126
43
|
protected
|
@@ -143,43 +60,32 @@ module SchemaPlus
|
|
143
60
|
|
144
61
|
foreign_keys = []
|
145
62
|
results.each do |row|
|
146
|
-
|
147
|
-
row["sql"].scan(re).each do |d0, name,
|
148
|
-
|
63
|
+
from_table = row["name"]
|
64
|
+
row["sql"].scan(re).each do |d0, name, columns, to_table, primary_keys, d1, on_update, d2, on_delete, deferrable, initially_deferred|
|
65
|
+
columns = columns.gsub(/`/, '').split(', ')
|
149
66
|
|
150
|
-
|
151
|
-
on_update = on_update
|
152
|
-
on_delete = on_delete
|
67
|
+
primary_keys = primary_keys.gsub(/[`"]/, '').split(', ')
|
68
|
+
on_update = ForeignKeyDefinition::ACTION_LOOKUP[on_update] || :no_action
|
69
|
+
on_delete = ForeignKeyDefinition::ACTION_LOOKUP[on_delete] || :no_action
|
153
70
|
deferrable = deferrable ? (initially_deferred ? :initially_deferred : true) : false
|
154
71
|
|
155
72
|
options = { :name => name,
|
156
73
|
:on_update => on_update,
|
157
74
|
:on_delete => on_delete,
|
158
|
-
:
|
159
|
-
:
|
75
|
+
:column => columns,
|
76
|
+
:primary_key => primary_keys,
|
160
77
|
:deferrable => deferrable }
|
161
78
|
|
162
|
-
foreign_keys << ForeignKeyDefinition.new(
|
163
|
-
|
164
|
-
|
79
|
+
foreign_keys << ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
|
80
|
+
from_table,
|
81
|
+
to_table,
|
82
|
+
options)
|
165
83
|
end
|
166
84
|
end
|
167
85
|
|
168
86
|
foreign_keys
|
169
87
|
end
|
170
88
|
|
171
|
-
module AddColumnOptions
|
172
|
-
def default_expr_valid?(expr)
|
173
|
-
true # arbitrary sql is okay
|
174
|
-
end
|
175
|
-
|
176
|
-
def sql_for_function(function)
|
177
|
-
case function
|
178
|
-
when :now
|
179
|
-
"(DATETIME('now'))"
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
183
89
|
end
|
184
90
|
|
185
91
|
end
|
@@ -64,133 +64,31 @@ module SchemaPlus::ActiveRecord::ConnectionAdapters
|
|
64
64
|
# end
|
65
65
|
#
|
66
66
|
module TableDefinition
|
67
|
-
include SchemaPlus::ActiveRecord::ColumnOptionsHandler
|
68
67
|
|
69
68
|
attr_accessor :schema_plus_config #:nodoc:
|
70
|
-
attr_reader :foreign_keys #:nodoc:
|
71
69
|
|
72
|
-
def
|
73
|
-
|
74
|
-
alias_method_chain :initialize, :schema_plus
|
75
|
-
alias_method_chain :column, :schema_plus
|
76
|
-
alias_method_chain :references, :schema_plus
|
77
|
-
alias_method_chain :belongs_to, :schema_plus
|
78
|
-
alias_method_chain :primary_key, :schema_plus
|
79
|
-
|
80
|
-
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
81
|
-
attr_accessor :name
|
82
|
-
attr_accessor :indexes
|
83
|
-
alias_method_chain :to_sql, :schema_plus
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def initialize_with_schema_plus(*args) #:nodoc:
|
89
|
-
initialize_without_schema_plus(*args)
|
90
|
-
@foreign_keys = []
|
91
|
-
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
92
|
-
@indexes = []
|
93
|
-
end
|
70
|
+
def foreign_keys
|
71
|
+
@foreign_keys ||= []
|
94
72
|
end
|
95
73
|
|
96
|
-
|
97
|
-
def primary_key_with_schema_plus(name, options = {}) #:nodoc:
|
98
|
-
column(name, :primary_key, options)
|
99
|
-
end
|
100
|
-
else
|
101
|
-
def primary_key_with_schema_plus(name, type = :primary_key, options = {}) #:nodoc:
|
102
|
-
column(name, type, options.merge(:primary_key => true))
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
|
107
|
-
# need detect :polymorphic at this level, because rails strips it out
|
108
|
-
# before calling #column (twice, once for _id and once for _type)
|
109
|
-
def references_with_schema_plus(*args) #:nodoc:
|
74
|
+
def foreign_key(*args) # (column_names, to_table, primary_key=nil, options=nil)
|
110
75
|
options = args.extract_options!
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
def belongs_to_with_schema_plus(*args) #:nodoc:
|
121
|
-
options = args.extract_options!
|
122
|
-
options[:references] = nil if options[:polymorphic]
|
123
|
-
schema_plus_normalize_column_options(options)
|
124
|
-
options[:_index] = options.delete(:index) unless options[:polymorphic] # usurp index creation from AR
|
125
|
-
args << options
|
126
|
-
belongs_to_without_schema_plus(*args)
|
127
|
-
end
|
128
|
-
|
129
|
-
def column_with_schema_plus(name, type, options = {}) #:nodoc:
|
130
|
-
schema_plus_normalize_column_options(options)
|
131
|
-
# prevent AR from seeing :index => false as a request for an index
|
132
|
-
if noindex = options[:index] == false
|
133
|
-
options.delete(:index)
|
76
|
+
case args.length
|
77
|
+
when 2
|
78
|
+
column_names, to_table = args
|
79
|
+
when 3
|
80
|
+
ActiveSupport::Deprecation.warn "positional arg for foreign primary key is deprecated, use :primary_key option instead"
|
81
|
+
column_names, to_table, primary_key = args
|
82
|
+
options.merge(:primary_key => primary_key)
|
83
|
+
else
|
84
|
+
raise ArgumentError, "wrong number of arguments (#{args.length}) for foreign_key(column_names, table_name, options)"
|
134
85
|
end
|
135
|
-
column_without_schema_plus(name, type, options)
|
136
|
-
options[:index] = false if noindex
|
137
|
-
schema_plus_handle_column_options(self.name, name, options, :config => schema_plus_config)
|
138
|
-
self
|
139
|
-
end
|
140
|
-
|
141
|
-
def to_sql_with_schema_plus #:nodoc:
|
142
|
-
sql = to_sql_without_schema_plus
|
143
|
-
sql << ', ' << @foreign_keys.map(&:to_sql) * ', ' unless @foreign_keys.empty?
|
144
|
-
sql
|
145
|
-
end
|
146
86
|
|
147
|
-
|
148
|
-
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
149
|
-
def index(column_name, options={})
|
150
|
-
@indexes << ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(self.name, column_name, options)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
def foreign_key(column_names, references_table_name, references_column_names, options = {})
|
155
|
-
options.merge!(:column_names => column_names, :references_column_names => references_column_names)
|
87
|
+
options.merge!(:column => column_names)
|
156
88
|
options.reverse_merge!(:name => ForeignKeyDefinition.default_name(self.name, column_names))
|
157
|
-
|
89
|
+
foreign_keys << ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(self.name, AbstractAdapter.proper_table_name(to_table), options)
|
158
90
|
self
|
159
91
|
end
|
160
92
|
|
161
|
-
protected
|
162
|
-
# The only purpose of that method is to provide a consistent intefrace
|
163
|
-
# for ColumnOptionsHandler. First argument (table name) is ignored.
|
164
|
-
def add_index(_, *args) #:nodoc:
|
165
|
-
index(*args)
|
166
|
-
end
|
167
|
-
|
168
|
-
# The only purpose of that method is to provide a consistent intefrace
|
169
|
-
# for ColumnOptionsHandler. First argument (table name) is ignored.
|
170
|
-
def add_foreign_key(_, *args) #:nodoc:
|
171
|
-
foreign_key(*args)
|
172
|
-
end
|
173
|
-
|
174
|
-
# This is a deliberately empty stub. The reason for it is that
|
175
|
-
# ColumnOptionsHandler is used for changes as well as for table
|
176
|
-
# definitions, and in the case of changes, previously existing foreign
|
177
|
-
# keys sometimes need to be removed. but in the case here, that of
|
178
|
-
# table definitions, the only reason a foreign key would exist is
|
179
|
-
# because we're redefining a table that already exists (via :force =>
|
180
|
-
# true). in which case the foreign key will get dropped when the
|
181
|
-
# drop_table gets emitted, so no need to do it immediately. (and for
|
182
|
-
# sqlite3, attempting to do it immediately would raise an error).
|
183
|
-
def remove_foreign_key(_, *args) #:nodoc:
|
184
|
-
end
|
185
|
-
|
186
|
-
# This is a deliberately empty stub. The reason for it is that
|
187
|
-
# ColumnOptionsHandler will remove a previous index when changing a
|
188
|
-
# column. But we don't do column changes within table definitions.
|
189
|
-
# Presumably will be called with :if_exists true. If not, will raise
|
190
|
-
# an error.
|
191
|
-
def remove_index(_, options)
|
192
|
-
raise "InternalError: remove_index called in a table definition" unless options[:if_exists]
|
193
|
-
end
|
194
|
-
|
195
93
|
end
|
196
94
|
end
|
@@ -2,26 +2,16 @@ module SchemaPlus
|
|
2
2
|
module ActiveRecord
|
3
3
|
module Migration
|
4
4
|
module CommandRecorder
|
5
|
-
include SchemaPlus::ActiveRecord::ColumnOptionsHandler
|
6
5
|
|
7
6
|
attr_accessor :schema_plus_config #:nodoc:
|
8
7
|
|
9
8
|
def self.included(base) #:nodoc:
|
10
9
|
base.class_eval do
|
11
|
-
alias_method_chain :
|
12
|
-
alias_method_chain :add_reference, :schema_plus unless ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
10
|
+
alias_method_chain :add_reference, :schema_plus
|
13
11
|
alias_method_chain :invert_add_index, :schema_plus
|
14
|
-
alias_method_chain :invert_add_foreign_key, :schema_plus if "#{::ActiveRecord::VERSION::MAJOR}.#{::ActiveRecord::VERSION::MINOR}".to_r >= "4.2".to_r
|
15
12
|
end
|
16
13
|
end
|
17
14
|
|
18
|
-
def add_column_with_schema_plus(table_name, name, type, options = {}) #:nodoc:
|
19
|
-
schema_plus_normalize_column_options(options)
|
20
|
-
add_column_without_schema_plus(table_name, name, type, options)
|
21
|
-
revertable_schema_plus_handle_column_options(table_name, name, options, :config => schema_plus_config)
|
22
|
-
self
|
23
|
-
end
|
24
|
-
|
25
15
|
# seems like this is fixing a rails bug:
|
26
16
|
# change_table foo, :bulk => true { |t| t.references :bar }
|
27
17
|
# results in an 'unknown method :add_reference_sql' (with mysql2)
|
@@ -29,63 +19,22 @@ module SchemaPlus
|
|
29
19
|
# should track it down separately and submit a patch/fix to rails
|
30
20
|
#
|
31
21
|
def add_reference_with_schema_plus(table_name, ref_name, options = {}) #:nodoc:
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
polymorphic = options.delete(:polymorphic)
|
40
|
-
index_options = options.delete(:index)
|
41
|
-
add_column(table_name, "#{ref_name}_id", :integer, options)
|
42
|
-
add_column(table_name, "#{ref_name}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic
|
43
|
-
add_index(table_name, polymorphic ? %w[id type].map{ |t| "#{ref_name}_#{t}" } : "#{ref_name}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options
|
44
|
-
end
|
22
|
+
polymorphic = options.delete(:polymorphic)
|
23
|
+
options[:references] = nil if polymorphic
|
24
|
+
# ugh. copying and pasting code from ::ActiveRecord::ConnectionAdapters::SchemaStatements#add_reference
|
25
|
+
index_options = options.delete(:index)
|
26
|
+
add_column(table_name, "#{ref_name}_id", :integer, options)
|
27
|
+
add_column(table_name, "#{ref_name}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic
|
28
|
+
add_index(table_name, polymorphic ? %w[id type].map{ |t| "#{ref_name}_#{t}" } : "#{ref_name}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options
|
45
29
|
|
46
30
|
self
|
47
31
|
end
|
48
32
|
|
49
|
-
if ::ActiveRecord::VERSION::MAJOR >= 4
|
50
|
-
def revertable_schema_plus_handle_column_options(table_name, name, options, config)
|
51
|
-
length = commands.length
|
52
|
-
schema_plus_handle_column_options(table_name, name, options, config)
|
53
|
-
if reverting
|
54
|
-
rev = []
|
55
|
-
while commands.length > length
|
56
|
-
cmd = commands.pop
|
57
|
-
rev.unshift cmd unless cmd[0].to_s =~ /^add_/
|
58
|
-
end
|
59
|
-
commands.concat rev
|
60
|
-
end
|
61
|
-
end
|
62
|
-
else
|
63
|
-
alias :revertable_schema_plus_handle_column_options :schema_plus_handle_column_options
|
64
|
-
end
|
65
|
-
|
66
|
-
def add_foreign_key(*args)
|
67
|
-
record(:add_foreign_key, args)
|
68
|
-
end
|
69
|
-
|
70
|
-
def invert_add_foreign_key(args)
|
71
|
-
table_name, column_names, references_table_name, references_column_names, options = args
|
72
|
-
[:remove_foreign_key, [table_name, column_names, references_table_name, references_column_names, (options||{}).merge(if_exists: true)]]
|
73
|
-
end
|
74
|
-
alias :invert_add_foreign_key_with_schema_plus :invert_add_foreign_key
|
75
|
-
|
76
33
|
def invert_add_index_with_schema_plus(args)
|
77
34
|
table, columns, options = *args
|
78
35
|
[:remove_index, [table, (options||{}).merge(column: columns, if_exists: true)]]
|
79
36
|
end
|
80
37
|
|
81
|
-
def remove_foreign_key(*args)
|
82
|
-
record(:remove_foreign_key, args)
|
83
|
-
end
|
84
|
-
|
85
|
-
def invert_remove_foreign_key(args)
|
86
|
-
[:add_foreign_key, args]
|
87
|
-
end
|
88
|
-
|
89
38
|
end
|
90
39
|
end
|
91
40
|
end
|