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
@@ -10,9 +10,6 @@ module ActiveRecord
|
|
10
10
|
# The +attributes+ parameter can be either a Hash or an Array of Hashes. These Hashes describe the
|
11
11
|
# attributes on the objects that are to be created.
|
12
12
|
#
|
13
|
-
# +create+ respects mass-assignment security and accepts either +:as+ or +:without_protection+ options
|
14
|
-
# in the +options+ parameter.
|
15
|
-
#
|
16
13
|
# ==== Examples
|
17
14
|
# # Create a single new object
|
18
15
|
# User.create(first_name: 'Jamie')
|
@@ -67,7 +64,7 @@ module ActiveRecord
|
|
67
64
|
end
|
68
65
|
|
69
66
|
# Returns true if this object hasn't been saved yet -- that is, a record
|
70
|
-
# for the object doesn't exist in the
|
67
|
+
# for the object doesn't exist in the database yet; otherwise, returns false.
|
71
68
|
def new_record?
|
72
69
|
sync_with_transaction_state
|
73
70
|
@new_record
|
@@ -198,7 +195,11 @@ module ActiveRecord
|
|
198
195
|
# share the same set of attributes.
|
199
196
|
def becomes!(klass)
|
200
197
|
became = becomes(klass)
|
201
|
-
|
198
|
+
sti_type = nil
|
199
|
+
if !klass.descends_from_active_record?
|
200
|
+
sti_type = klass.sti_name
|
201
|
+
end
|
202
|
+
became.public_send("#{klass.inheritance_column}=", sti_type)
|
202
203
|
became
|
203
204
|
end
|
204
205
|
|
@@ -386,7 +387,7 @@ module ActiveRecord
|
|
386
387
|
|
387
388
|
fresh_object =
|
388
389
|
if options && options[:lock]
|
389
|
-
self.class.unscoped { self.class.lock.find(id) }
|
390
|
+
self.class.unscoped { self.class.lock(options[:lock]).find(id) }
|
390
391
|
else
|
391
392
|
self.class.unscoped { self.class.find(id) }
|
392
393
|
end
|
@@ -249,7 +249,7 @@ db_namespace = namespace :db do
|
|
249
249
|
desc 'Load a schema.rb file into the database'
|
250
250
|
task :load => [:environment, :load_config] do
|
251
251
|
file = ENV['SCHEMA'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'schema.rb')
|
252
|
-
if File.
|
252
|
+
if File.exist?(file)
|
253
253
|
load(file)
|
254
254
|
else
|
255
255
|
abort %{#{file} doesn't exist yet. Run `rake db:migrate` to create it, then try again. If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded.}
|
@@ -274,7 +274,7 @@ db_namespace = namespace :db do
|
|
274
274
|
desc 'Clear a db/schema_cache.dump file.'
|
275
275
|
task :clear => [:environment, :load_config] do
|
276
276
|
filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.dump")
|
277
|
-
FileUtils.rm(filename) if File.
|
277
|
+
FileUtils.rm(filename) if File.exist?(filename)
|
278
278
|
end
|
279
279
|
end
|
280
280
|
|
@@ -344,7 +344,7 @@ db_namespace = namespace :db do
|
|
344
344
|
end
|
345
345
|
|
346
346
|
# desc "Recreate the test database from a fresh schema"
|
347
|
-
task :clone do
|
347
|
+
task :clone => :environment do
|
348
348
|
case ActiveRecord::Base.schema_format
|
349
349
|
when :ruby
|
350
350
|
db_namespace["test:clone_schema"].invoke
|
@@ -365,7 +365,7 @@ db_namespace = namespace :db do
|
|
365
365
|
end
|
366
366
|
|
367
367
|
# desc 'Check for pending migrations and load the test schema'
|
368
|
-
task :prepare => :load_config do
|
368
|
+
task :prepare => [:environment, :load_config] do
|
369
369
|
unless ActiveRecord::Base.configurations.blank?
|
370
370
|
db_namespace['test:load'].invoke
|
371
371
|
end
|
@@ -402,4 +402,3 @@ namespace :railties do
|
|
402
402
|
end
|
403
403
|
|
404
404
|
task 'test:prepare' => ['db:test:prepare', 'db:test:load', 'db:abort_if_pending_migrations']
|
405
|
-
|
@@ -71,16 +71,13 @@ module ActiveRecord
|
|
71
71
|
while records.any?
|
72
72
|
records_size = records.size
|
73
73
|
primary_key_offset = records.last.id
|
74
|
+
raise "Primary key not included in the custom select clause" unless primary_key_offset
|
74
75
|
|
75
76
|
yield records
|
76
77
|
|
77
78
|
break if records_size < batch_size
|
78
79
|
|
79
|
-
|
80
|
-
records = relation.where(table[primary_key].gt(primary_key_offset)).to_a
|
81
|
-
else
|
82
|
-
raise "Primary key not included in the custom select clause"
|
83
|
-
end
|
80
|
+
records = relation.where(table[primary_key].gt(primary_key_offset)).to_a
|
84
81
|
end
|
85
82
|
end
|
86
83
|
|
@@ -332,7 +332,9 @@ module ActiveRecord
|
|
332
332
|
}
|
333
333
|
key = key.first if key.size == 1
|
334
334
|
key = key_records[key] if associated
|
335
|
-
|
335
|
+
|
336
|
+
column_type = calculated_data.column_types.fetch(aggregate_alias) { column_for(column_name) }
|
337
|
+
[key, type_cast_calculated_value(row[aggregate_alias], column_type, operation)]
|
336
338
|
end]
|
337
339
|
end
|
338
340
|
|
@@ -4,11 +4,12 @@ module ActiveRecord
|
|
4
4
|
# If no record can be found for all of the listed ids, then RecordNotFound will be raised. If the primary key
|
5
5
|
# is an integer, find by id coerces its arguments using +to_i+.
|
6
6
|
#
|
7
|
-
# Person.find(1)
|
8
|
-
# Person.find("1")
|
9
|
-
# Person.find(
|
10
|
-
# Person.find(
|
11
|
-
# Person.find([
|
7
|
+
# Person.find(1) # returns the object for ID = 1
|
8
|
+
# Person.find("1") # returns the object for ID = 1
|
9
|
+
# Person.find("31-sarah") # returns the object for ID = 31
|
10
|
+
# Person.find(1, 2, 6) # returns an array for objects with IDs in (1, 2, 6)
|
11
|
+
# Person.find([7, 17]) # returns an array for objects with IDs in (7, 17)
|
12
|
+
# Person.find([1]) # returns an array for the object with ID = 1
|
12
13
|
# Person.where("administrator = 1").order("created_on DESC").find(1)
|
13
14
|
#
|
14
15
|
# Note that returned records may not be in the same order as the ids you
|
@@ -107,13 +107,29 @@ module ActiveRecord
|
|
107
107
|
def merge_multi_values
|
108
108
|
lhs_wheres = relation.where_values
|
109
109
|
rhs_wheres = values[:where] || []
|
110
|
+
|
110
111
|
lhs_binds = relation.bind_values
|
111
112
|
rhs_binds = values[:bind] || []
|
112
113
|
|
113
114
|
removed, kept = partition_overwrites(lhs_wheres, rhs_wheres)
|
114
115
|
|
115
|
-
|
116
|
-
|
116
|
+
where_values = kept + rhs_wheres
|
117
|
+
bind_values = filter_binds(lhs_binds, removed) + rhs_binds
|
118
|
+
|
119
|
+
conn = relation.klass.connection
|
120
|
+
bv_index = 0
|
121
|
+
where_values.map! do |node|
|
122
|
+
if Arel::Nodes::Equality === node && Arel::Nodes::BindParam === node.right
|
123
|
+
substitute = conn.substitute_at(bind_values[bv_index].first, bv_index)
|
124
|
+
bv_index += 1
|
125
|
+
Arel::Nodes::Equality.new(node.left, substitute)
|
126
|
+
else
|
127
|
+
node
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
relation.where_values = where_values
|
132
|
+
relation.bind_values = bind_values
|
117
133
|
|
118
134
|
if values[:reordering]
|
119
135
|
# override any order specified in the original relation
|
@@ -609,12 +609,11 @@ module ActiveRecord
|
|
609
609
|
self
|
610
610
|
end
|
611
611
|
|
612
|
-
# Returns a chainable relation with zero records
|
613
|
-
# instance of the <tt>ActiveRecord::NullRelation</tt> class.
|
612
|
+
# Returns a chainable relation with zero records.
|
614
613
|
#
|
615
|
-
# The returned
|
616
|
-
#
|
617
|
-
#
|
614
|
+
# The returned relation implements the Null Object pattern. It is an
|
615
|
+
# object with defined null behavior and always returns an empty array of
|
616
|
+
# records without querying the database.
|
618
617
|
#
|
619
618
|
# Any subsequent condition chained to the returned relation will continue
|
620
619
|
# generating an empty relation and will not fire any query to the database.
|
@@ -849,7 +848,7 @@ module ActiveRecord
|
|
849
848
|
|
850
849
|
where_values.reject! do |rel|
|
851
850
|
case rel
|
852
|
-
when Arel::Nodes::In, Arel::Nodes::Equality
|
851
|
+
when Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual
|
853
852
|
subrelation = (rel.left.kind_of?(Arel::Attributes::Attribute) ? rel.left : rel.right)
|
854
853
|
subrelation.name.to_sym == target_value_sym
|
855
854
|
else
|
@@ -99,8 +99,9 @@ module ActiveRecord
|
|
99
99
|
# { status: nil, group_id: 1 }
|
100
100
|
# # => "status = NULL , group_id = 1"
|
101
101
|
def sanitize_sql_hash_for_assignment(attrs, table)
|
102
|
+
c = connection
|
102
103
|
attrs.map do |attr, value|
|
103
|
-
"#{
|
104
|
+
"#{c.quote_table_name_for_assignment(table, attr)} = #{quote_bound_value(value, c, columns_hash[attr.to_s])}"
|
104
105
|
end.join(', ')
|
105
106
|
end
|
106
107
|
|
@@ -151,8 +152,10 @@ module ActiveRecord
|
|
151
152
|
end
|
152
153
|
end
|
153
154
|
|
154
|
-
def quote_bound_value(value, c = connection) #:nodoc:
|
155
|
-
if
|
155
|
+
def quote_bound_value(value, c = connection, column = nil) #:nodoc:
|
156
|
+
if column
|
157
|
+
c.quote(value, column)
|
158
|
+
elsif value.respond_to?(:map) && !value.acts_like?(:string)
|
156
159
|
if value.respond_to?(:empty?) && value.empty?
|
157
160
|
c.quote(nil)
|
158
161
|
else
|
data/lib/active_record/store.rb
CHANGED
@@ -134,8 +134,9 @@ IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
|
|
134
134
|
args << "--password=#{configuration['password']}" if configuration['password']
|
135
135
|
args.concat(['--default-character-set', configuration['encoding']]) if configuration['encoding']
|
136
136
|
configuration.slice('host', 'port', 'socket').each do |k, v|
|
137
|
-
args.concat([ "--#{k}", v ]) if v
|
137
|
+
args.concat([ "--#{k}", v.to_s ]) if v
|
138
138
|
end
|
139
|
+
|
139
140
|
args
|
140
141
|
end
|
141
142
|
end
|
@@ -10,9 +10,9 @@ module ActiveRecord
|
|
10
10
|
#
|
11
11
|
# config.active_record.record_timestamps = false
|
12
12
|
#
|
13
|
-
# Timestamps are in
|
13
|
+
# Timestamps are in UTC by default but you can use the local timezone by setting:
|
14
14
|
#
|
15
|
-
# config.active_record.default_timezone = :
|
15
|
+
# config.active_record.default_timezone = :local
|
16
16
|
#
|
17
17
|
# == Time Zone aware attributes
|
18
18
|
#
|
@@ -218,8 +218,8 @@ module ActiveRecord
|
|
218
218
|
# after_commit :do_bar, on: :update
|
219
219
|
# after_commit :do_baz, on: :destroy
|
220
220
|
#
|
221
|
-
# after_commit :do_foo_bar, :
|
222
|
-
# after_commit :do_bar_baz, :
|
221
|
+
# after_commit :do_foo_bar, on: [:create, :update]
|
222
|
+
# after_commit :do_bar_baz, on: [:update, :destroy]
|
223
223
|
#
|
224
224
|
# Note that transactional fixtures do not play well with this feature. Please
|
225
225
|
# use the +test_after_commit+ gem to have these hooks fired in tests.
|
@@ -275,6 +275,10 @@ module ActiveRecord
|
|
275
275
|
with_transaction_returning_status { super }
|
276
276
|
end
|
277
277
|
|
278
|
+
def touch(*) #:nodoc:
|
279
|
+
with_transaction_returning_status { super }
|
280
|
+
end
|
281
|
+
|
278
282
|
# Reset id and @new_record if the transaction rolls back.
|
279
283
|
def rollback_active_record_state!
|
280
284
|
remember_transaction_record_state
|
@@ -293,7 +297,7 @@ module ActiveRecord
|
|
293
297
|
def committed! #:nodoc:
|
294
298
|
run_callbacks :commit if destroyed? || persisted?
|
295
299
|
ensure
|
296
|
-
|
300
|
+
@_start_transaction_state.clear
|
297
301
|
end
|
298
302
|
|
299
303
|
# Call the +after_rollback+ callbacks. The +force_restore_state+ argument indicates if the record
|
@@ -5,7 +5,7 @@ module ActiveRecord
|
|
5
5
|
super
|
6
6
|
attributes.each do |attribute|
|
7
7
|
next unless record.class.reflect_on_association(attribute)
|
8
|
-
associated_records = Array(record.send(attribute))
|
8
|
+
associated_records = Array.wrap(record.send(attribute))
|
9
9
|
|
10
10
|
# Superclass validates presence. Ensure present records aren't about to be destroyed.
|
11
11
|
if associated_records.present? && associated_records.all? { |r| r.marked_for_destruction? }
|
@@ -53,10 +53,18 @@ module ActiveRecord
|
|
53
53
|
def build_relation(klass, table, attribute, value) #:nodoc:
|
54
54
|
if reflection = klass.reflect_on_association(attribute)
|
55
55
|
attribute = reflection.foreign_key
|
56
|
-
value = value.attributes[reflection.primary_key_column.name]
|
56
|
+
value = value.attributes[reflection.primary_key_column.name] unless value.nil?
|
57
57
|
end
|
58
58
|
|
59
|
-
|
59
|
+
attribute_name = attribute.to_s
|
60
|
+
|
61
|
+
# the attribute may be an aliased attribute
|
62
|
+
if klass.attribute_aliases[attribute_name]
|
63
|
+
attribute = klass.attribute_aliases[attribute_name]
|
64
|
+
attribute_name = attribute.to_s
|
65
|
+
end
|
66
|
+
|
67
|
+
column = klass.columns_hash[attribute_name]
|
60
68
|
value = klass.connection.type_cast(value, column)
|
61
69
|
value = value.to_s[0, column.limit] if value && column.limit && column.text?
|
62
70
|
|
@@ -171,11 +179,11 @@ module ActiveRecord
|
|
171
179
|
# WHERE title = 'My Post' |
|
172
180
|
# |
|
173
181
|
# | # User 2 does the same thing and also
|
174
|
-
# | # infers that
|
182
|
+
# | # infers that their title is unique.
|
175
183
|
# | SELECT * FROM comments
|
176
184
|
# | WHERE title = 'My Post'
|
177
185
|
# |
|
178
|
-
# # User 1 inserts
|
186
|
+
# # User 1 inserts their comment. |
|
179
187
|
# INSERT INTO comments |
|
180
188
|
# (title, content) VALUES |
|
181
189
|
# ('My Post', 'hi!') |
|
@@ -201,7 +209,7 @@ module ActiveRecord
|
|
201
209
|
# exception. You can either choose to let this error propagate (which
|
202
210
|
# will result in the default Rails exception page being shown), or you
|
203
211
|
# can catch it and restart the transaction (e.g. by telling the user
|
204
|
-
# that the title already exists, and asking
|
212
|
+
# that the title already exists, and asking them to re-enter the title).
|
205
213
|
# This technique is also known as
|
206
214
|
# {optimistic concurrency control}[http://en.wikipedia.org/wiki/Optimistic_concurrency_control].
|
207
215
|
#
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.
|
4
|
+
version: 4.0.4.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 4.0.
|
19
|
+
version: 4.0.4.rc1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 4.0.
|
26
|
+
version: 4.0.4.rc1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activemodel
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 4.0.
|
33
|
+
version: 4.0.4.rc1
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 4.0.
|
40
|
+
version: 4.0.4.rc1
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: arel
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -255,12 +255,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
255
255
|
version: 1.9.3
|
256
256
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
257
257
|
requirements:
|
258
|
-
- - "
|
258
|
+
- - ">"
|
259
259
|
- !ruby/object:Gem::Version
|
260
|
-
version:
|
260
|
+
version: 1.3.1
|
261
261
|
requirements: []
|
262
262
|
rubyforge_project:
|
263
|
-
rubygems_version: 2.2.
|
263
|
+
rubygems_version: 2.2.2
|
264
264
|
signing_key:
|
265
265
|
specification_version: 4
|
266
266
|
summary: Object-relational mapper framework (part of Rails).
|