activerecord 4.2.1 → 4.2.7.1
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 +368 -1
- data/lib/active_record/aggregations.rb +4 -3
- data/lib/active_record/association_relation.rb +13 -0
- data/lib/active_record/associations/association.rb +15 -3
- data/lib/active_record/associations/association_scope.rb +1 -0
- data/lib/active_record/associations/belongs_to_association.rb +5 -1
- data/lib/active_record/associations/builder/association.rb +1 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +8 -4
- data/lib/active_record/associations/collection_association.rb +1 -7
- data/lib/active_record/associations/collection_proxy.rb +8 -7
- data/lib/active_record/associations/has_many_association.rb +8 -1
- data/lib/active_record/associations/has_many_through_association.rb +9 -0
- data/lib/active_record/associations/join_dependency.rb +8 -2
- data/lib/active_record/associations/preloader/association.rb +5 -1
- data/lib/active_record/associations/preloader.rb +4 -4
- data/lib/active_record/associations/singular_association.rb +2 -8
- data/lib/active_record/associations/through_association.rb +0 -6
- data/lib/active_record/associations.rb +1 -1
- data/lib/active_record/attribute_assignment.rb +1 -1
- data/lib/active_record/attribute_methods/dirty.rb +7 -1
- data/lib/active_record/attribute_methods.rb +3 -7
- data/lib/active_record/attribute_set/builder.rb +21 -11
- data/lib/active_record/attribute_set.rb +4 -0
- data/lib/active_record/autosave_association.rb +1 -1
- data/lib/active_record/base.rb +4 -5
- data/lib/active_record/callbacks.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +4 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +11 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +16 -24
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +49 -17
- data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +12 -1
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +38 -5
- data/lib/active_record/connection_adapters/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +3 -3
- data/lib/active_record/connection_adapters/mysql_adapter.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +17 -5
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +9 -9
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -12
- data/lib/active_record/core.rb +15 -8
- data/lib/active_record/enum.rb +2 -3
- data/lib/active_record/errors.rb +6 -5
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixtures.rb +8 -6
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/legacy_yaml_adapter.rb +30 -0
- data/lib/active_record/migration.rb +7 -4
- data/lib/active_record/model_schema.rb +1 -1
- data/lib/active_record/nested_attributes.rb +12 -2
- data/lib/active_record/persistence.rb +5 -3
- data/lib/active_record/railtie.rb +1 -1
- data/lib/active_record/railties/databases.rake +10 -7
- data/lib/active_record/reflection.rb +39 -27
- data/lib/active_record/relation/calculations.rb +8 -1
- data/lib/active_record/relation/delegation.rb +1 -1
- data/lib/active_record/relation/finder_methods.rb +3 -15
- data/lib/active_record/relation/merger.rb +24 -1
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -1
- data/lib/active_record/relation/predicate_builder.rb +11 -2
- data/lib/active_record/relation/query_methods.rb +15 -18
- data/lib/active_record/relation/spawn_methods.rb +7 -3
- data/lib/active_record/relation.rb +2 -1
- data/lib/active_record/scoping/default.rb +1 -0
- data/lib/active_record/tasks/database_tasks.rb +3 -2
- data/lib/active_record/tasks/mysql_database_tasks.rb +30 -16
- data/lib/active_record/tasks/postgresql_database_tasks.rb +19 -8
- data/lib/active_record/transactions.rb +16 -4
- data/lib/active_record/type/boolean.rb +1 -0
- data/lib/active_record/type/date.rb +4 -0
- data/lib/active_record/type/decimal.rb +12 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +8 -2
- data/lib/active_record/type/serialized.rb +7 -1
- data/lib/active_record/validations/uniqueness.rb +15 -5
- data/lib/active_record.rb +2 -0
- metadata +9 -7
@@ -10,13 +10,13 @@ module ActiveRecord
|
|
10
10
|
# end
|
11
11
|
#
|
12
12
|
# class Book < ActiveRecord::Base
|
13
|
-
# # columns: title, sales
|
13
|
+
# # columns: title, sales, author_id
|
14
14
|
# end
|
15
15
|
#
|
16
16
|
# When you load an author with all associated books Active Record will make
|
17
17
|
# multiple queries like this:
|
18
18
|
#
|
19
|
-
# Author.includes(:books).where(:
|
19
|
+
# Author.includes(:books).where(name: ['bell hooks', 'Homer']).to_a
|
20
20
|
#
|
21
21
|
# => SELECT `authors`.* FROM `authors` WHERE `name` IN ('bell hooks', 'Homer')
|
22
22
|
# => SELECT `books`.* FROM `books` WHERE `author_id` IN (2, 5)
|
@@ -160,7 +160,7 @@ module ActiveRecord
|
|
160
160
|
h
|
161
161
|
end
|
162
162
|
|
163
|
-
class AlreadyLoaded
|
163
|
+
class AlreadyLoaded # :nodoc:
|
164
164
|
attr_reader :owners, :reflection
|
165
165
|
|
166
166
|
def initialize(klass, owners, reflection, preload_scope)
|
@@ -175,7 +175,7 @@ module ActiveRecord
|
|
175
175
|
end
|
176
176
|
end
|
177
177
|
|
178
|
-
class NullPreloader
|
178
|
+
class NullPreloader # :nodoc:
|
179
179
|
def self.new(klass, owners, reflection, preload_scope); self; end
|
180
180
|
def self.run(preloader); end
|
181
181
|
def self.preloaded_records; []; end
|
@@ -3,7 +3,7 @@ module ActiveRecord
|
|
3
3
|
class SingularAssociation < Association #:nodoc:
|
4
4
|
# Implements the reader method, e.g. foo.bar for Foo.has_one :bar
|
5
5
|
def reader(force_reload = false)
|
6
|
-
if force_reload
|
6
|
+
if force_reload && klass
|
7
7
|
klass.uncached { reload }
|
8
8
|
elsif !loaded? || stale_target?
|
9
9
|
reload
|
@@ -39,13 +39,7 @@ module ActiveRecord
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def get_records
|
42
|
-
|
43
|
-
scope.eager_loading? ||
|
44
|
-
klass.current_scope ||
|
45
|
-
klass.default_scopes.any?
|
46
|
-
|
47
|
-
return scope.limit(1).to_a
|
48
|
-
end
|
42
|
+
return scope.limit(1).to_a if skip_statement_cache?
|
49
43
|
|
50
44
|
conn = klass.connection
|
51
45
|
sc = reflection.association_scope_cache(conn, owner) do
|
@@ -15,12 +15,6 @@ module ActiveRecord
|
|
15
15
|
scope = super
|
16
16
|
reflection.chain.drop(1).each do |reflection|
|
17
17
|
relation = reflection.klass.all
|
18
|
-
|
19
|
-
reflection_scope = reflection.scope
|
20
|
-
if reflection_scope && reflection_scope.arity.zero?
|
21
|
-
relation.merge!(reflection_scope)
|
22
|
-
end
|
23
|
-
|
24
18
|
scope.merge!(
|
25
19
|
relation.except(:select, :create_with, :includes, :preload, :joins, :eager_load)
|
26
20
|
)
|
@@ -1713,7 +1713,7 @@ module ActiveRecord
|
|
1713
1713
|
hm_options[:through] = middle_reflection.name
|
1714
1714
|
hm_options[:source] = join_model.right_reflection.name
|
1715
1715
|
|
1716
|
-
[:before_add, :after_add, :before_remove, :after_remove, :autosave, :validate, :join_table, :class_name].each do |k|
|
1716
|
+
[:before_add, :after_add, :before_remove, :after_remove, :autosave, :validate, :join_table, :class_name, :extend].each do |k|
|
1717
1717
|
hm_options[k] = options[k] if options.key? k
|
1718
1718
|
end
|
1719
1719
|
|
@@ -40,6 +40,7 @@ module ActiveRecord
|
|
40
40
|
|
41
41
|
def initialize_dup(other) # :nodoc:
|
42
42
|
super
|
43
|
+
@original_raw_attributes = nil
|
43
44
|
calculate_changes_from_defaults
|
44
45
|
end
|
45
46
|
|
@@ -108,6 +109,7 @@ module ActiveRecord
|
|
108
109
|
end
|
109
110
|
|
110
111
|
def save_changed_attribute(attr, old_value)
|
112
|
+
clear_changed_attributes_cache
|
111
113
|
if attribute_changed_by_setter?(attr)
|
112
114
|
clear_attribute_changes(attr) unless _field_changed?(attr, old_value)
|
113
115
|
else
|
@@ -178,7 +180,11 @@ module ActiveRecord
|
|
178
180
|
@cached_changed_attributes = changed_attributes
|
179
181
|
yield
|
180
182
|
ensure
|
181
|
-
|
183
|
+
clear_changed_attributes_cache
|
184
|
+
end
|
185
|
+
|
186
|
+
def clear_changed_attributes_cache
|
187
|
+
remove_instance_variable(:@cached_changed_attributes) if defined?(@cached_changed_attributes)
|
182
188
|
end
|
183
189
|
end
|
184
190
|
end
|
@@ -287,9 +287,8 @@ module ActiveRecord
|
|
287
287
|
# Returns an <tt>#inspect</tt>-like string for the value of the
|
288
288
|
# attribute +attr_name+. String attributes are truncated up to 50
|
289
289
|
# characters, Date and Time attributes are returned in the
|
290
|
-
# <tt>:db</tt> format
|
291
|
-
#
|
292
|
-
# modification.
|
290
|
+
# <tt>:db</tt> format. Other attributes return the value of
|
291
|
+
# <tt>#inspect</tt> without modification.
|
293
292
|
#
|
294
293
|
# person = Person.create!(name: 'David Heinemeier Hansson ' * 3)
|
295
294
|
#
|
@@ -300,7 +299,7 @@ module ActiveRecord
|
|
300
299
|
# # => "\"2012-10-22 00:15:07\""
|
301
300
|
#
|
302
301
|
# person.attribute_for_inspect(:tag_ids)
|
303
|
-
# # => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
302
|
+
# # => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]"
|
304
303
|
def attribute_for_inspect(attr_name)
|
305
304
|
value = read_attribute(attr_name)
|
306
305
|
|
@@ -308,9 +307,6 @@ module ActiveRecord
|
|
308
307
|
"#{value[0, 50]}...".inspect
|
309
308
|
elsif value.is_a?(Date) || value.is_a?(Time)
|
310
309
|
%("#{value.to_s(:db)}")
|
311
|
-
elsif value.is_a?(Array) && value.size > 10
|
312
|
-
inspected = value.first(10).inspect
|
313
|
-
%(#{inspected[0...-1]}, ...])
|
314
310
|
else
|
315
311
|
value.inspect
|
316
312
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_record/attribute'
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
class AttributeSet # :nodoc:
|
3
5
|
class Builder # :nodoc:
|
@@ -64,10 +66,29 @@ module ActiveRecord
|
|
64
66
|
end
|
65
67
|
end
|
66
68
|
|
69
|
+
def ==(other)
|
70
|
+
if other.is_a?(LazyAttributeHash)
|
71
|
+
materialize == other.materialize
|
72
|
+
else
|
73
|
+
materialize == other
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
67
77
|
protected
|
68
78
|
|
69
79
|
attr_reader :types, :values, :additional_types, :delegate_hash
|
70
80
|
|
81
|
+
def materialize
|
82
|
+
unless @materialized
|
83
|
+
values.each_key { |key| self[key] }
|
84
|
+
types.each_key { |key| self[key] }
|
85
|
+
unless frozen?
|
86
|
+
@materialized = true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
delegate_hash
|
90
|
+
end
|
91
|
+
|
71
92
|
private
|
72
93
|
|
73
94
|
def assign_default_value(name)
|
@@ -81,16 +102,5 @@ module ActiveRecord
|
|
81
102
|
delegate_hash[name] = Attribute.uninitialized(name, type)
|
82
103
|
end
|
83
104
|
end
|
84
|
-
|
85
|
-
def materialize
|
86
|
-
unless @materialized
|
87
|
-
values.each_key { |key| self[key] }
|
88
|
-
types.each_key { |key| self[key] }
|
89
|
-
unless frozen?
|
90
|
-
@materialized = true
|
91
|
-
end
|
92
|
-
end
|
93
|
-
delegate_hash
|
94
|
-
end
|
95
105
|
end
|
96
106
|
end
|
@@ -318,7 +318,7 @@ module ActiveRecord
|
|
318
318
|
# the parent, <tt>self</tt>, if it wasn't. Skips any <tt>:autosave</tt>
|
319
319
|
# enabled records if they're marked_for_destruction? or destroyed.
|
320
320
|
def association_valid?(reflection, record)
|
321
|
-
return true if record.destroyed? || record.marked_for_destruction?
|
321
|
+
return true if record.destroyed? || (reflection.options[:autosave] && record.marked_for_destruction?)
|
322
322
|
|
323
323
|
validation_context = self.validation_context unless [:create, :update].include?(self.validation_context)
|
324
324
|
unless valid = record.valid?(validation_context)
|
data/lib/active_record/base.rb
CHANGED
@@ -119,23 +119,22 @@ module ActiveRecord #:nodoc:
|
|
119
119
|
# All column values are automatically available through basic accessors on the Active Record
|
120
120
|
# object, but sometimes you want to specialize this behavior. This can be done by overwriting
|
121
121
|
# the default accessors (using the same name as the attribute) and calling
|
122
|
-
#
|
123
|
-
# change things.
|
122
|
+
# +super+ to actually change things.
|
124
123
|
#
|
125
124
|
# class Song < ActiveRecord::Base
|
126
125
|
# # Uses an integer of seconds to hold the length of the song
|
127
126
|
#
|
128
127
|
# def length=(minutes)
|
129
|
-
#
|
128
|
+
# super(minutes.to_i * 60)
|
130
129
|
# end
|
131
130
|
#
|
132
131
|
# def length
|
133
|
-
#
|
132
|
+
# super / 60
|
134
133
|
# end
|
135
134
|
# end
|
136
135
|
#
|
137
136
|
# You can alternatively use <tt>self[:attribute]=(value)</tt> and <tt>self[:attribute]</tt>
|
138
|
-
#
|
137
|
+
# or <tt>write_attribute(:attribute, value)</tt> and <tt>read_attribute(:attribute)</tt>.
|
139
138
|
#
|
140
139
|
# == Attribute query methods
|
141
140
|
#
|
@@ -199,7 +199,7 @@ module ActiveRecord
|
|
199
199
|
# == Canceling callbacks
|
200
200
|
#
|
201
201
|
# If a <tt>before_*</tt> callback returns +false+, all the later callbacks and the associated action are
|
202
|
-
# cancelled.
|
202
|
+
# cancelled.
|
203
203
|
# Callbacks are generally run in the order they are defined, with the exception of callbacks defined as
|
204
204
|
# methods on the model, which are called last.
|
205
205
|
#
|
@@ -234,6 +234,10 @@ module ActiveRecord
|
|
234
234
|
current_transaction.add_record(record)
|
235
235
|
end
|
236
236
|
|
237
|
+
def transaction_state
|
238
|
+
current_transaction.state
|
239
|
+
end
|
240
|
+
|
237
241
|
# Begins the transaction (and turns off auto-committing).
|
238
242
|
def begin_db_transaction() end
|
239
243
|
|
@@ -283,12 +287,17 @@ module ActiveRecord
|
|
283
287
|
# Inserts the given fixture into the table. Overridden in adapters that require
|
284
288
|
# something beyond a simple insert (eg. Oracle).
|
285
289
|
def insert_fixture(fixture, table_name)
|
290
|
+
fixture = fixture.stringify_keys
|
286
291
|
columns = schema_cache.columns_hash(table_name)
|
287
292
|
|
288
293
|
key_list = []
|
289
294
|
value_list = fixture.map do |name, value|
|
290
|
-
|
291
|
-
|
295
|
+
if column = columns[name]
|
296
|
+
key_list << quote_column_name(name)
|
297
|
+
quote(value, column)
|
298
|
+
else
|
299
|
+
raise Fixture::FixtureError, %(table "#{table_name}" has no column named #{name.inspect}.)
|
300
|
+
end
|
292
301
|
end
|
293
302
|
|
294
303
|
execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})", 'Fixture Insert'
|
@@ -57,11 +57,11 @@ module ActiveRecord
|
|
57
57
|
end
|
58
58
|
|
59
59
|
module TimestampDefaultDeprecation # :nodoc:
|
60
|
-
def emit_warning_if_null_unspecified(options)
|
60
|
+
def emit_warning_if_null_unspecified(sym, options)
|
61
61
|
return if options.key?(:null)
|
62
62
|
|
63
63
|
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
64
|
-
|
64
|
+
`##{sym}` was called without specifying an option for `null`. In Rails 5,
|
65
65
|
this behavior will change to `null: false`. You should manually specify
|
66
66
|
`null: true` to prevent the behavior of your existing migrations from changing.
|
67
67
|
MSG
|
@@ -99,7 +99,7 @@ module ActiveRecord
|
|
99
99
|
def initialize(types, name, temporary, options, as = nil)
|
100
100
|
@columns_hash = {}
|
101
101
|
@indexes = {}
|
102
|
-
@foreign_keys =
|
102
|
+
@foreign_keys = []
|
103
103
|
@native = types
|
104
104
|
@temporary = temporary
|
105
105
|
@options = options
|
@@ -256,6 +256,7 @@ module ActiveRecord
|
|
256
256
|
def column(name, type, options = {})
|
257
257
|
name = name.to_s
|
258
258
|
type = type.to_sym
|
259
|
+
options = options.dup
|
259
260
|
|
260
261
|
if @columns_hash[name] && @columns_hash[name].primary_key?
|
261
262
|
raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
|
@@ -288,7 +289,7 @@ module ActiveRecord
|
|
288
289
|
end
|
289
290
|
|
290
291
|
def foreign_key(table_name, options = {}) # :nodoc:
|
291
|
-
foreign_keys[table_name
|
292
|
+
foreign_keys.push([table_name, options])
|
292
293
|
end
|
293
294
|
|
294
295
|
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
|
@@ -297,23 +298,17 @@ module ActiveRecord
|
|
297
298
|
# t.timestamps null: false
|
298
299
|
def timestamps(*args)
|
299
300
|
options = args.extract_options!
|
300
|
-
emit_warning_if_null_unspecified(options)
|
301
|
+
emit_warning_if_null_unspecified(:timestamps, options)
|
301
302
|
column(:created_at, :datetime, options)
|
302
303
|
column(:updated_at, :datetime, options)
|
303
304
|
end
|
304
305
|
|
305
|
-
# Adds a reference.
|
306
|
-
# <tt>:polymorphic</tt> option is provided. <tt>references</tt> and
|
307
|
-
# <tt>belongs_to</tt> are acceptable. The reference column will be an
|
308
|
-
# +integer+ by default, the <tt>:type</tt> option can be used to specify
|
309
|
-
# a different type. A foreign key will be created if a +foreign_key+
|
310
|
-
# option is passed.
|
306
|
+
# Adds a reference.
|
311
307
|
#
|
312
308
|
# t.references(:user)
|
313
|
-
# t.
|
314
|
-
# t.belongs_to(:supplier, polymorphic: true)
|
309
|
+
# t.belongs_to(:supplier, foreign_key: true)
|
315
310
|
#
|
316
|
-
# See SchemaStatements#add_reference
|
311
|
+
# See SchemaStatements#add_reference for details of the options you can use.
|
317
312
|
def references(*args)
|
318
313
|
options = args.extract_options!
|
319
314
|
polymorphic = options.delete(:polymorphic)
|
@@ -329,7 +324,10 @@ module ActiveRecord
|
|
329
324
|
column("#{col}_id", type, options)
|
330
325
|
column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic
|
331
326
|
index(polymorphic ? %w(type id).map { |t| "#{col}_#{t}" } : "#{col}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options
|
332
|
-
|
327
|
+
if foreign_key_options
|
328
|
+
to_table = Base.pluralize_table_names ? col.to_s.pluralize : col.to_s
|
329
|
+
foreign_key(to_table, foreign_key_options.is_a?(Hash) ? foreign_key_options : {})
|
330
|
+
end
|
333
331
|
end
|
334
332
|
end
|
335
333
|
alias :belongs_to :references
|
@@ -535,18 +533,12 @@ module ActiveRecord
|
|
535
533
|
@base.rename_column(name, column_name, new_column_name)
|
536
534
|
end
|
537
535
|
|
538
|
-
# Adds a reference.
|
539
|
-
# <tt>:polymorphic</tt> option is provided. <tt>references</tt> and
|
540
|
-
# <tt>belongs_to</tt> are acceptable. The reference column will be an
|
541
|
-
# +integer+ by default, the <tt>:type</tt> option can be used to specify
|
542
|
-
# a different type. A foreign key will be created if a +foreign_key+
|
543
|
-
# option is passed.
|
536
|
+
# Adds a reference.
|
544
537
|
#
|
545
538
|
# t.references(:user)
|
546
|
-
# t.
|
547
|
-
# t.belongs_to(:supplier, polymorphic: true)
|
539
|
+
# t.belongs_to(:supplier, foreign_key: true)
|
548
540
|
#
|
549
|
-
# See SchemaStatements#add_reference
|
541
|
+
# See SchemaStatements#add_reference for details of the options you can use.
|
550
542
|
def references(*args)
|
551
543
|
options = args.extract_options!
|
552
544
|
args.each do |ref_name|
|
@@ -19,6 +19,20 @@ module ActiveRecord
|
|
19
19
|
table_name[0...table_alias_length].tr('.', '_')
|
20
20
|
end
|
21
21
|
|
22
|
+
# Returns the relation names useable to back Active Record models.
|
23
|
+
# For most adapters this means all tables and views.
|
24
|
+
def data_sources
|
25
|
+
tables
|
26
|
+
end
|
27
|
+
|
28
|
+
# Checks to see if the data source +name+ exists on the database.
|
29
|
+
#
|
30
|
+
# data_source_exists?(:ebooks)
|
31
|
+
#
|
32
|
+
def data_source_exists?(name)
|
33
|
+
data_sources.include?(name.to_s)
|
34
|
+
end
|
35
|
+
|
22
36
|
# Checks to see if the table +table_name+ exists on the database.
|
23
37
|
#
|
24
38
|
# table_exists?(:developers)
|
@@ -213,7 +227,7 @@ module ActiveRecord
|
|
213
227
|
end
|
214
228
|
end
|
215
229
|
|
216
|
-
td.foreign_keys.
|
230
|
+
td.foreign_keys.each do |other_table_name, foreign_key_options|
|
217
231
|
add_foreign_key(table_name, other_table_name, foreign_key_options)
|
218
232
|
end
|
219
233
|
|
@@ -530,6 +544,8 @@ module ActiveRecord
|
|
530
544
|
#
|
531
545
|
# CREATE UNIQUE INDEX index_accounts_on_branch_id_and_party_id ON accounts(branch_id, party_id) WHERE active
|
532
546
|
#
|
547
|
+
# Note: Partial indexes are only supported for PostgreSQL and SQLite 3.8.0+.
|
548
|
+
#
|
533
549
|
# ====== Creating an index with a specific method
|
534
550
|
#
|
535
551
|
# add_index(:developers, :name, using: 'btree')
|
@@ -621,11 +637,21 @@ module ActiveRecord
|
|
621
637
|
indexes(table_name).detect { |i| i.name == index_name }
|
622
638
|
end
|
623
639
|
|
624
|
-
# Adds a reference.
|
625
|
-
#
|
626
|
-
# a
|
640
|
+
# Adds a reference. The reference column is an integer by default,
|
641
|
+
# the <tt>:type</tt> option can be used to specify a different type.
|
642
|
+
# Optionally adds a +_type+ column, if <tt>:polymorphic</tt> option is provided.
|
627
643
|
# <tt>add_reference</tt> and <tt>add_belongs_to</tt> are acceptable.
|
628
644
|
#
|
645
|
+
# The +options+ hash can include the following keys:
|
646
|
+
# [<tt>:type</tt>]
|
647
|
+
# The reference column type. Defaults to +:integer+.
|
648
|
+
# [<tt>:index</tt>]
|
649
|
+
# Add an appropriate index. Defaults to false.
|
650
|
+
# [<tt>:foreign_key</tt>]
|
651
|
+
# Add an appropriate foreign key. Defaults to false.
|
652
|
+
# [<tt>:polymorphic</tt>]
|
653
|
+
# Wether an additional +_type+ column should be added. Defaults to false.
|
654
|
+
#
|
629
655
|
# ====== Create a user_id integer column
|
630
656
|
#
|
631
657
|
# add_reference(:products, :user)
|
@@ -634,10 +660,6 @@ module ActiveRecord
|
|
634
660
|
#
|
635
661
|
# add_reference(:products, :user, type: :string)
|
636
662
|
#
|
637
|
-
# ====== Create a supplier_id and supplier_type columns
|
638
|
-
#
|
639
|
-
# add_belongs_to(:products, :supplier, polymorphic: true)
|
640
|
-
#
|
641
663
|
# ====== Create supplier_id, supplier_type columns and appropriate index
|
642
664
|
#
|
643
665
|
# add_reference(:products, :supplier, polymorphic: true, index: true)
|
@@ -655,7 +677,10 @@ module ActiveRecord
|
|
655
677
|
add_column(table_name, "#{ref_name}_id", type, options)
|
656
678
|
add_column(table_name, "#{ref_name}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic
|
657
679
|
add_index(table_name, polymorphic ? %w[type id].map{ |t| "#{ref_name}_#{t}" } : "#{ref_name}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options
|
658
|
-
|
680
|
+
if foreign_key_options
|
681
|
+
to_table = Base.pluralize_table_names ? ref_name.to_s.pluralize : ref_name
|
682
|
+
add_foreign_key(table_name, to_table, foreign_key_options.is_a?(Hash) ? foreign_key_options : {})
|
683
|
+
end
|
659
684
|
end
|
660
685
|
alias :add_belongs_to :add_reference
|
661
686
|
|
@@ -675,7 +700,10 @@ module ActiveRecord
|
|
675
700
|
# remove_reference(:products, :user, index: true, foreign_key: true)
|
676
701
|
#
|
677
702
|
def remove_reference(table_name, ref_name, options = {})
|
678
|
-
|
703
|
+
if options[:foreign_key]
|
704
|
+
to_table = Base.pluralize_table_names ? ref_name.to_s.pluralize : ref_name
|
705
|
+
remove_foreign_key(table_name, to_table)
|
706
|
+
end
|
679
707
|
|
680
708
|
remove_column(table_name, "#{ref_name}_id")
|
681
709
|
remove_column(table_name, "#{ref_name}_type") if options[:polymorphic]
|
@@ -692,8 +720,8 @@ module ActiveRecord
|
|
692
720
|
# +to_table+ contains the referenced primary key.
|
693
721
|
#
|
694
722
|
# The foreign key will be named after the following pattern: <tt>fk_rails_<identifier></tt>.
|
695
|
-
# +identifier+ is a 10 character long
|
696
|
-
# the <tt>:name</tt> option.
|
723
|
+
# +identifier+ is a 10 character long string which is deterministically generated from the
|
724
|
+
# +from_table+ and +column+. A custom name can be specified with the <tt>:name</tt> option.
|
697
725
|
#
|
698
726
|
# ====== Creating a simple foreign key
|
699
727
|
#
|
@@ -705,7 +733,7 @@ module ActiveRecord
|
|
705
733
|
#
|
706
734
|
# ====== Creating a foreign key on a specific column
|
707
735
|
#
|
708
|
-
# add_foreign_key :articles, :users, column: :author_id, primary_key:
|
736
|
+
# add_foreign_key :articles, :users, column: :author_id, primary_key: :lng_id
|
709
737
|
#
|
710
738
|
# generates:
|
711
739
|
#
|
@@ -788,7 +816,10 @@ module ActiveRecord
|
|
788
816
|
end
|
789
817
|
|
790
818
|
def foreign_key_column_for(table_name) # :nodoc:
|
791
|
-
|
819
|
+
prefix = Base.table_name_prefix
|
820
|
+
suffix = Base.table_name_suffix
|
821
|
+
name = table_name.to_s =~ /#{prefix}(.+)#{suffix}/ ? $1 : table_name.to_s
|
822
|
+
"#{name.singularize}_id"
|
792
823
|
end
|
793
824
|
|
794
825
|
def dump_schema_information #:nodoc:
|
@@ -859,11 +890,12 @@ module ActiveRecord
|
|
859
890
|
end
|
860
891
|
|
861
892
|
# Given a set of columns and an ORDER BY clause, returns the columns for a SELECT DISTINCT.
|
862
|
-
#
|
893
|
+
# PostgreSQL, MySQL, and Oracle overrides this for custom DISTINCT syntax - they
|
863
894
|
# require the order columns appear in the SELECT.
|
864
895
|
#
|
865
896
|
# columns_for_distinct("posts.id", ["posts.created_at desc"])
|
866
|
-
|
897
|
+
#
|
898
|
+
def columns_for_distinct(columns, orders) # :nodoc:
|
867
899
|
columns
|
868
900
|
end
|
869
901
|
|
@@ -874,7 +906,7 @@ module ActiveRecord
|
|
874
906
|
# add_timestamps(:suppliers, null: false)
|
875
907
|
#
|
876
908
|
def add_timestamps(table_name, options = {})
|
877
|
-
emit_warning_if_null_unspecified(options)
|
909
|
+
emit_warning_if_null_unspecified(:add_timestamps, options)
|
878
910
|
add_column table_name, :created_at, :datetime, options
|
879
911
|
add_column table_name, :updated_at, :datetime, options
|
880
912
|
end
|
@@ -111,6 +111,18 @@ module ActiveRecord
|
|
111
111
|
@prepared_statements = false
|
112
112
|
end
|
113
113
|
|
114
|
+
class Version
|
115
|
+
include Comparable
|
116
|
+
|
117
|
+
def initialize(version_string)
|
118
|
+
@version = version_string.split('.').map(&:to_i)
|
119
|
+
end
|
120
|
+
|
121
|
+
def <=>(version_string)
|
122
|
+
@version <=> version_string.split('.').map(&:to_i)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
114
126
|
class BindCollector < Arel::Collectors::Bind
|
115
127
|
def compile(bvs, conn)
|
116
128
|
super(bvs.map { |bv| conn.quote(*bv.reverse) })
|
@@ -457,7 +469,6 @@ module ActiveRecord
|
|
457
469
|
message = "#{e.class.name}: #{e.message.force_encoding sql.encoding}: #{sql}"
|
458
470
|
end
|
459
471
|
|
460
|
-
@logger.error message if @logger
|
461
472
|
exception = translate_exception(e, message)
|
462
473
|
exception.set_backtrace e.backtrace
|
463
474
|
exception
|