activerecord 4.0.3 → 4.0.4.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +412 -0
- data/lib/active_record/associations.rb +2 -2
- data/lib/active_record/associations/association.rb +7 -2
- data/lib/active_record/associations/association_scope.rb +7 -2
- data/lib/active_record/associations/builder/belongs_to.rb +9 -3
- data/lib/active_record/associations/builder/singular_association.rb +1 -1
- data/lib/active_record/associations/collection_association.rb +1 -1
- data/lib/active_record/associations/collection_proxy.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +1 -1
- data/lib/active_record/associations/has_one_association.rb +4 -2
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/attribute_methods.rb +32 -15
- data/lib/active_record/attribute_methods/serialization.rb +10 -0
- data/lib/active_record/autosave_association.rb +8 -2
- data/lib/active_record/callbacks.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +14 -3
- data/lib/active_record/connection_adapters/abstract/quoting.rb +3 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +9 -9
- data/lib/active_record/connection_adapters/abstract/transaction.rb +4 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +7 -0
- data/lib/active_record/connection_adapters/column.rb +11 -3
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/mysql_adapter.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/cast.rb +12 -8
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +20 -15
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +7 -3
- data/lib/active_record/core.rb +17 -9
- data/lib/active_record/counter_cache.rb +1 -1
- data/lib/active_record/dynamic_matchers.rb +7 -2
- data/lib/active_record/inheritance.rb +15 -7
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/migration.rb +10 -6
- data/lib/active_record/migration/command_recorder.rb +12 -5
- data/lib/active_record/persistence.rb +7 -6
- data/lib/active_record/railties/databases.rake +4 -5
- data/lib/active_record/relation/batches.rb +2 -5
- data/lib/active_record/relation/calculations.rb +3 -1
- data/lib/active_record/relation/finder_methods.rb +6 -5
- data/lib/active_record/relation/merger.rb +18 -2
- data/lib/active_record/relation/query_methods.rb +5 -6
- data/lib/active_record/sanitization.rb +6 -3
- data/lib/active_record/store.rb +1 -1
- data/lib/active_record/tasks/mysql_database_tasks.rb +2 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
- data/lib/active_record/timestamp.rb +2 -2
- data/lib/active_record/transactions.rb +7 -3
- data/lib/active_record/validations/presence.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +13 -5
- data/lib/active_record/version.rb +1 -1
- metadata +9 -9
@@ -207,7 +207,7 @@ module ActiveRecord
|
|
207
207
|
|
208
208
|
# Returns an array of arrays containing the field values.
|
209
209
|
# Order is the same as that returned by +columns+.
|
210
|
-
def select_rows(sql, name = nil)
|
210
|
+
def select_rows(sql, name = nil, binds = [])
|
211
211
|
execute(sql, name).to_a
|
212
212
|
end
|
213
213
|
|
@@ -213,9 +213,9 @@ module ActiveRecord
|
|
213
213
|
|
214
214
|
# DATABASE STATEMENTS ======================================
|
215
215
|
|
216
|
-
def select_rows(sql, name = nil)
|
216
|
+
def select_rows(sql, name = nil, binds = [])
|
217
217
|
@connection.query_with_result = true
|
218
|
-
rows = exec_query(sql, name).rows
|
218
|
+
rows = exec_query(sql, name, binds).rows
|
219
219
|
@connection.more_results && @connection.next_result # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped
|
220
220
|
rows
|
221
221
|
end
|
@@ -84,8 +84,9 @@ module ActiveRecord
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def add_item_to_array(array, current_item, quoted)
|
87
|
-
if current_item.length == 0
|
88
|
-
|
87
|
+
return if !quoted && current_item.length == 0
|
88
|
+
|
89
|
+
if !quoted && current_item == 'NULL'
|
89
90
|
array.push nil
|
90
91
|
else
|
91
92
|
array.push current_item
|
@@ -35,11 +35,11 @@ module ActiveRecord
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
def hstore_to_string(object)
|
38
|
+
def hstore_to_string(object, array_member = false)
|
39
39
|
if Hash === object
|
40
|
-
object.map { |k,v|
|
41
|
-
|
42
|
-
|
40
|
+
string = object.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(',')
|
41
|
+
string = escape_hstore(string) if array_member
|
42
|
+
string
|
43
43
|
else
|
44
44
|
object
|
45
45
|
end
|
@@ -49,10 +49,10 @@ module ActiveRecord
|
|
49
49
|
if string.nil?
|
50
50
|
nil
|
51
51
|
elsif String === string
|
52
|
-
Hash[string.scan(HstorePair).map { |k,v|
|
52
|
+
Hash[string.scan(HstorePair).map { |k, v|
|
53
53
|
v = v.upcase == 'NULL' ? nil : v.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
|
54
54
|
k = k.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
|
55
|
-
[k,v]
|
55
|
+
[k, v]
|
56
56
|
}]
|
57
57
|
else
|
58
58
|
string
|
@@ -100,7 +100,11 @@ module ActiveRecord
|
|
100
100
|
if string.nil?
|
101
101
|
nil
|
102
102
|
elsif String === string
|
103
|
-
|
103
|
+
begin
|
104
|
+
IPAddr.new(string)
|
105
|
+
rescue ArgumentError
|
106
|
+
nil
|
107
|
+
end
|
104
108
|
else
|
105
109
|
string
|
106
110
|
end
|
@@ -142,7 +146,7 @@ module ActiveRecord
|
|
142
146
|
|
143
147
|
def quote_and_escape(value)
|
144
148
|
case value
|
145
|
-
when "NULL"
|
149
|
+
when "NULL", Numeric
|
146
150
|
value
|
147
151
|
else
|
148
152
|
value = value.gsub(/\\/, ARRAY_ESCAPE)
|
@@ -46,8 +46,8 @@ module ActiveRecord
|
|
46
46
|
|
47
47
|
# Executes a SELECT query and returns an array of rows. Each row is an
|
48
48
|
# array of field values.
|
49
|
-
def select_rows(sql, name = nil)
|
50
|
-
|
49
|
+
def select_rows(sql, name = nil, binds = [])
|
50
|
+
exec_query(sql, name, binds).rows
|
51
51
|
end
|
52
52
|
|
53
53
|
# Executes an INSERT query and returns the new record's ID
|
@@ -109,7 +109,7 @@ module ActiveRecord
|
|
109
109
|
{ :value => value, :format => 1 }
|
110
110
|
when Hash
|
111
111
|
case column.sql_type
|
112
|
-
when 'hstore' then PostgreSQLColumn.hstore_to_string(value)
|
112
|
+
when 'hstore' then PostgreSQLColumn.hstore_to_string(value, array_member)
|
113
113
|
when 'json' then PostgreSQLColumn.json_to_string(value)
|
114
114
|
else super(value, column)
|
115
115
|
end
|
@@ -126,6 +126,19 @@ module ActiveRecord
|
|
126
126
|
SQL
|
127
127
|
end
|
128
128
|
|
129
|
+
def index_name_exists?(table_name, index_name, default)
|
130
|
+
exec_query(<<-SQL, 'SCHEMA').rows.first[0].to_i > 0
|
131
|
+
SELECT COUNT(*)
|
132
|
+
FROM pg_class t
|
133
|
+
INNER JOIN pg_index d ON t.oid = d.indrelid
|
134
|
+
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
135
|
+
WHERE i.relkind = 'i'
|
136
|
+
AND i.relname = '#{index_name}'
|
137
|
+
AND t.relname = '#{table_name}'
|
138
|
+
AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = ANY (current_schemas(false)) )
|
139
|
+
SQL
|
140
|
+
end
|
141
|
+
|
129
142
|
# Returns an array of indexes for the given table.
|
130
143
|
def indexes(table_name, name = nil)
|
131
144
|
result = query(<<-SQL, 'SCHEMA')
|
@@ -46,7 +46,7 @@ module ActiveRecord
|
|
46
46
|
# PostgreSQL-specific extensions to column definitions in a table.
|
47
47
|
class PostgreSQLColumn < Column #:nodoc:
|
48
48
|
attr_accessor :array
|
49
|
-
|
49
|
+
|
50
50
|
def initialize(name, default, oid_type, sql_type = nil, null = true)
|
51
51
|
@oid_type = oid_type
|
52
52
|
default_value = self.class.extract_value_from_default(default)
|
@@ -62,6 +62,14 @@ module ActiveRecord
|
|
62
62
|
@default_function = default if has_default_function?(default_value, default)
|
63
63
|
end
|
64
64
|
|
65
|
+
def number?
|
66
|
+
!array && super
|
67
|
+
end
|
68
|
+
|
69
|
+
def text?
|
70
|
+
!array && super
|
71
|
+
end
|
72
|
+
|
65
73
|
# :stopdoc:
|
66
74
|
class << self
|
67
75
|
include ConnectionAdapters::PostgreSQLColumn::Cast
|
@@ -565,11 +573,16 @@ module ActiveRecord
|
|
565
573
|
|
566
574
|
# Is this connection alive and ready for queries?
|
567
575
|
def active?
|
568
|
-
@connection.
|
576
|
+
@connection.query 'SELECT 1'
|
577
|
+
true
|
569
578
|
rescue PGError
|
570
579
|
false
|
571
580
|
end
|
572
581
|
|
582
|
+
def active_threadsafe?
|
583
|
+
@connection.connect_poll != PG::PGRES_POLLING_FAILED
|
584
|
+
end
|
585
|
+
|
573
586
|
# Close then reopen the connection.
|
574
587
|
def reconnect!
|
575
588
|
super
|
@@ -706,6 +719,10 @@ module ActiveRecord
|
|
706
719
|
!native_database_types[type].nil?
|
707
720
|
end
|
708
721
|
|
722
|
+
def update_table_definition(table_name, base) #:nodoc:
|
723
|
+
Table.new(table_name, base)
|
724
|
+
end
|
725
|
+
|
709
726
|
protected
|
710
727
|
|
711
728
|
# Returns the version of the connected PostgreSQL server.
|
@@ -768,7 +785,7 @@ module ActiveRecord
|
|
768
785
|
end
|
769
786
|
end
|
770
787
|
|
771
|
-
FEATURE_NOT_SUPPORTED = "0A000"
|
788
|
+
FEATURE_NOT_SUPPORTED = "0A000" #:nodoc:
|
772
789
|
|
773
790
|
def exec_no_cache(sql, binds)
|
774
791
|
@connection.async_exec(sql)
|
@@ -891,14 +908,6 @@ module ActiveRecord
|
|
891
908
|
exec_query(sql, name, binds)
|
892
909
|
end
|
893
910
|
|
894
|
-
def select_raw(sql, name = nil)
|
895
|
-
res = execute(sql, name)
|
896
|
-
results = result_as_array(res)
|
897
|
-
fields = res.fields
|
898
|
-
res.clear
|
899
|
-
return fields, results
|
900
|
-
end
|
901
|
-
|
902
911
|
# Returns the list of a table's column names, data types, and default values.
|
903
912
|
#
|
904
913
|
# The underlying query is roughly:
|
@@ -947,10 +956,6 @@ module ActiveRecord
|
|
947
956
|
def create_table_definition(name, temporary, options)
|
948
957
|
TableDefinition.new native_database_types, name, temporary, options
|
949
958
|
end
|
950
|
-
|
951
|
-
def update_table_definition(table_name, base)
|
952
|
-
Table.new(table_name, base)
|
953
|
-
end
|
954
959
|
end
|
955
960
|
end
|
956
961
|
end
|
@@ -347,8 +347,8 @@ module ActiveRecord
|
|
347
347
|
end
|
348
348
|
alias :create :insert_sql
|
349
349
|
|
350
|
-
def select_rows(sql, name = nil)
|
351
|
-
exec_query(sql, name).rows
|
350
|
+
def select_rows(sql, name = nil, binds = [])
|
351
|
+
exec_query(sql, name, binds).rows
|
352
352
|
end
|
353
353
|
|
354
354
|
def create_savepoint
|
@@ -616,7 +616,11 @@ module ActiveRecord
|
|
616
616
|
|
617
617
|
def translate_exception(exception, message)
|
618
618
|
case exception.message
|
619
|
-
|
619
|
+
# SQLite 3.8.2 returns a newly formatted error message:
|
620
|
+
# UNIQUE constraint failed: *table_name*.*column_name*
|
621
|
+
# Older versions of SQLite return:
|
622
|
+
# column *column_name* is not unique
|
623
|
+
when /column(s)? .* (is|are) not unique/, /UNIQUE constraint failed: .*/
|
620
624
|
RecordNotUnique.new(message, exception)
|
621
625
|
else
|
622
626
|
super
|
data/lib/active_record/core.rb
CHANGED
@@ -112,7 +112,7 @@ module ActiveRecord
|
|
112
112
|
elsif abstract_class?
|
113
113
|
"#{super}(abstract)"
|
114
114
|
elsif !connected?
|
115
|
-
"#{super}(
|
115
|
+
"#{super} (call '#{super}.connection' to establish a connection)"
|
116
116
|
elsif table_exists?
|
117
117
|
attr_list = columns.map { |c| "#{c.name}: #{c.type}" } * ', '
|
118
118
|
"#{super}(#{attr_list})"
|
@@ -129,7 +129,7 @@ module ActiveRecord
|
|
129
129
|
# Returns an instance of <tt>Arel::Table</tt> loaded with the current table name.
|
130
130
|
#
|
131
131
|
# class Post < ActiveRecord::Base
|
132
|
-
# scope :published_and_commented, published.and(self.arel_table[:comments_count].gt(0))
|
132
|
+
# scope :published_and_commented, -> { published.and(self.arel_table[:comments_count].gt(0)) }
|
133
133
|
# end
|
134
134
|
def arel_table
|
135
135
|
@arel_table ||= Arel::Table.new(table_name, arel_engine)
|
@@ -275,7 +275,7 @@ module ActiveRecord
|
|
275
275
|
# Post.new.encode_with(coder)
|
276
276
|
# coder # => {"attributes" => {"id" => nil, ... }}
|
277
277
|
def encode_with(coder)
|
278
|
-
coder['attributes'] =
|
278
|
+
coder['attributes'] = attributes_for_coder
|
279
279
|
end
|
280
280
|
|
281
281
|
# Returns true if +comparison_object+ is the same exact object, or +comparison_object+
|
@@ -373,6 +373,17 @@ module ActiveRecord
|
|
373
373
|
!_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_create_callbacks.empty?
|
374
374
|
end
|
375
375
|
|
376
|
+
# Required to deserialize Syck properly.
|
377
|
+
if YAML.const_defined?(:ENGINE) && YAML::ENGINE.syck?
|
378
|
+
ActiveSupport::Deprecation.warn(
|
379
|
+
"Syck is deprecated and support for serialization has been removed." \
|
380
|
+
" ActiveRecord::Core#yaml_initialize will be removed in 4.1 which will break deserialization support with Syck."
|
381
|
+
)
|
382
|
+
def yaml_initialize(tag, coder) # :nodoc:
|
383
|
+
init_with(coder)
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
376
387
|
private
|
377
388
|
|
378
389
|
# Updates the attributes on this particular ActiveRecord object so that
|
@@ -397,13 +408,10 @@ module ActiveRecord
|
|
397
408
|
end
|
398
409
|
|
399
410
|
def update_attributes_from_transaction_state(transaction_state, depth)
|
400
|
-
if transaction_state && !has_transactional_callbacks?
|
411
|
+
if transaction_state && transaction_state.finalized? && !has_transactional_callbacks?
|
401
412
|
unless @reflects_state[depth]
|
402
|
-
if transaction_state.
|
403
|
-
|
404
|
-
elsif transaction_state.rolledback?
|
405
|
-
rolledback!
|
406
|
-
end
|
413
|
+
restore_transaction_record_state if transaction_state.rolledback?
|
414
|
+
clear_transaction_record_state
|
407
415
|
@reflects_state[depth] = true
|
408
416
|
end
|
409
417
|
|
@@ -77,7 +77,7 @@ module ActiveRecord
|
|
77
77
|
"#{quoted_column} = COALESCE(#{quoted_column}, 0) #{operator} #{value.abs}"
|
78
78
|
end
|
79
79
|
|
80
|
-
where(primary_key => id).update_all updates.join(', ')
|
80
|
+
unscoped.where(primary_key => id).update_all updates.join(', ')
|
81
81
|
end
|
82
82
|
|
83
83
|
# Increment a numeric field by one, via a direct SQL update.
|
@@ -84,13 +84,18 @@ module ActiveRecord
|
|
84
84
|
"#{finder}(#{attributes_hash})"
|
85
85
|
end
|
86
86
|
|
87
|
+
# The parameters in the signature may have reserved Ruby words, in order
|
88
|
+
# to prevent errors, we start each param name with `_`.
|
89
|
+
#
|
87
90
|
# Extended in activerecord-deprecated_finders
|
88
91
|
def signature
|
89
|
-
attribute_names.join(', ')
|
92
|
+
attribute_names.map { |name| "_#{name}" }.join(', ')
|
90
93
|
end
|
91
94
|
|
95
|
+
# Given that the parameters starts with `_`, the finder needs to use the
|
96
|
+
# same parameter name.
|
92
97
|
def attributes_hash
|
93
|
-
"{" + attribute_names.map { |name| ":#{name} => #{name}" }.join(',') + "}"
|
98
|
+
"{" + attribute_names.map { |name| ":#{name} => _#{name}" }.join(',') + "}"
|
94
99
|
end
|
95
100
|
|
96
101
|
def finder
|
@@ -18,13 +18,17 @@ module ActiveRecord
|
|
18
18
|
if abstract_class? || self == Base
|
19
19
|
raise NotImplementedError, "#{self} is an abstract class and can not be instantiated."
|
20
20
|
end
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
|
22
|
+
attrs = args.first
|
23
|
+
if subclass_from_attributes?(attrs)
|
24
|
+
subclass = subclass_from_attributes(attrs)
|
25
|
+
end
|
26
|
+
|
27
|
+
if subclass
|
28
|
+
subclass.new(*args, &block)
|
29
|
+
else
|
30
|
+
super
|
25
31
|
end
|
26
|
-
# Delegate to the original .new
|
27
|
-
super
|
28
32
|
end
|
29
33
|
|
30
34
|
# True if this isn't a concrete subclass needing a STI type condition.
|
@@ -168,7 +172,11 @@ module ActiveRecord
|
|
168
172
|
# is not self or a valid subclass, raises ActiveRecord::SubclassNotFound
|
169
173
|
# If this is a StrongParameters hash, and access to inheritance_column is not permitted,
|
170
174
|
# this will ignore the inheritance column and return nil
|
171
|
-
def
|
175
|
+
def subclass_from_attributes?(attrs)
|
176
|
+
columns_hash.include?(inheritance_column) && attrs.is_a?(Hash)
|
177
|
+
end
|
178
|
+
|
179
|
+
def subclass_from_attributes(attrs)
|
172
180
|
subclass_name = attrs.with_indifferent_access[inheritance_column]
|
173
181
|
|
174
182
|
if subclass_name.present? && subclass_name != self.name
|
@@ -3,12 +3,12 @@ module ActiveRecord
|
|
3
3
|
# Locking::Pessimistic provides support for row-level locking using
|
4
4
|
# SELECT ... FOR UPDATE and other lock types.
|
5
5
|
#
|
6
|
-
#
|
6
|
+
# Chain <tt>ActiveRecord::Base#find</tt> to <tt>ActiveRecord::QueryMethods#lock</tt> to obtain an exclusive
|
7
7
|
# lock on the selected rows:
|
8
8
|
# # select * from accounts where id=1 for update
|
9
|
-
# Account.find(1
|
9
|
+
# Account.lock.find(1)
|
10
10
|
#
|
11
|
-
#
|
11
|
+
# Call <tt>lock('some locking clause')</tt> to use a database-specific locking clause
|
12
12
|
# of your own such as 'LOCK IN SHARE MODE' or 'FOR UPDATE NOWAIT'. Example:
|
13
13
|
#
|
14
14
|
# Account.transaction do
|
@@ -32,7 +32,11 @@ module ActiveRecord
|
|
32
32
|
|
33
33
|
class PendingMigrationError < ActiveRecordError#:nodoc:
|
34
34
|
def initialize
|
35
|
-
|
35
|
+
if defined?(Rails)
|
36
|
+
super("Migrations are pending; run 'bin/rake db:migrate RAILS_ENV=#{::Rails.env}' to resolve this issue.")
|
37
|
+
else
|
38
|
+
super("Migrations are pending; run 'bin/rake db:migrate' to resolve this issue.")
|
39
|
+
end
|
36
40
|
end
|
37
41
|
end
|
38
42
|
|
@@ -120,8 +124,8 @@ module ActiveRecord
|
|
120
124
|
# a column but keeps the type and content.
|
121
125
|
# * <tt>change_column(table_name, column_name, type, options)</tt>: Changes
|
122
126
|
# the column to a different type using the same parameters as add_column.
|
123
|
-
# * <tt>remove_column(table_name,
|
124
|
-
# +
|
127
|
+
# * <tt>remove_column(table_name, column_name, type, options)</tt>: Removes the column
|
128
|
+
# named +column_name+ from the table called +table_name+.
|
125
129
|
# * <tt>add_index(table_name, column_names, options)</tt>: Adds a new index
|
126
130
|
# with the name of the column. Other options include
|
127
131
|
# <tt>:name</tt>, <tt>:unique</tt> (e.g.
|
@@ -629,7 +633,7 @@ module ActiveRecord
|
|
629
633
|
def copy(destination, sources, options = {})
|
630
634
|
copied = []
|
631
635
|
|
632
|
-
FileUtils.mkdir_p(destination) unless File.
|
636
|
+
FileUtils.mkdir_p(destination) unless File.exist?(destination)
|
633
637
|
|
634
638
|
destination_migrations = ActiveRecord::Migrator.migrations(destination)
|
635
639
|
last = destination_migrations.last
|
@@ -716,7 +720,7 @@ module ActiveRecord
|
|
716
720
|
|
717
721
|
def load_migration
|
718
722
|
require(File.expand_path(filename))
|
719
|
-
name.constantize.new
|
723
|
+
name.constantize.new(name, version)
|
720
724
|
end
|
721
725
|
|
722
726
|
end
|
@@ -875,7 +879,7 @@ module ActiveRecord
|
|
875
879
|
|
876
880
|
validate(@migrations)
|
877
881
|
|
878
|
-
|
882
|
+
Base.connection.initialize_schema_migrations_table
|
879
883
|
end
|
880
884
|
|
881
885
|
def current_version
|
@@ -86,7 +86,7 @@ module ActiveRecord
|
|
86
86
|
alias :remove_belongs_to :remove_reference
|
87
87
|
|
88
88
|
def change_table(table_name, options = {})
|
89
|
-
yield
|
89
|
+
yield delegate.update_table_definition(table_name, self)
|
90
90
|
end
|
91
91
|
|
92
92
|
private
|
@@ -139,7 +139,12 @@ module ActiveRecord
|
|
139
139
|
|
140
140
|
def invert_add_index(args)
|
141
141
|
table, columns, options = *args
|
142
|
-
|
142
|
+
options ||= {}
|
143
|
+
|
144
|
+
index_name = options[:name]
|
145
|
+
options_hash = index_name ? { name: index_name } : { column: columns }
|
146
|
+
|
147
|
+
[:remove_index, [table, options_hash]]
|
143
148
|
end
|
144
149
|
|
145
150
|
def invert_remove_index(args)
|
@@ -158,9 +163,11 @@ module ActiveRecord
|
|
158
163
|
|
159
164
|
# Forwards any missing method call to the \target.
|
160
165
|
def method_missing(method, *args, &block)
|
161
|
-
@delegate.
|
162
|
-
|
163
|
-
|
166
|
+
if @delegate.respond_to?(method)
|
167
|
+
@delegate.send(method, *args, &block)
|
168
|
+
else
|
169
|
+
super
|
170
|
+
end
|
164
171
|
end
|
165
172
|
end
|
166
173
|
end
|