activerecord 3.1.0.rc4 → 3.1.0.rc5
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.
- data/CHANGELOG +25 -0
- data/lib/active_record/associations.rb +6 -5
- data/lib/active_record/associations/alias_tracker.rb +12 -24
- data/lib/active_record/associations/association.rb +56 -6
- data/lib/active_record/associations/belongs_to_association.rb +1 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +10 -12
- data/lib/active_record/associations/collection_association.rb +44 -31
- data/lib/active_record/associations/collection_proxy.rb +11 -4
- data/lib/active_record/associations/has_one_association.rb +1 -1
- data/lib/active_record/associations/join_helper.rb +1 -2
- data/lib/active_record/associations/preloader/association.rb +3 -2
- data/lib/active_record/associations/singular_association.rb +12 -4
- data/lib/active_record/attribute_methods.rb +1 -1
- data/lib/active_record/attribute_methods/primary_key.rb +1 -1
- data/lib/active_record/attribute_methods/read.rb +3 -2
- data/lib/active_record/autosave_association.rb +1 -1
- data/lib/active_record/base.rb +78 -30
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +18 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +6 -6
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +4 -4
- data/lib/active_record/connection_adapters/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +5 -0
- data/lib/active_record/locking/optimistic.rb +1 -1
- data/lib/active_record/migration.rb +6 -2
- data/lib/active_record/migration/command_recorder.rb +1 -1
- data/lib/active_record/named_scope.rb +19 -0
- data/lib/active_record/nested_attributes.rb +18 -12
- data/lib/active_record/persistence.rb +8 -3
- data/lib/active_record/query_cache.rb +8 -0
- data/lib/active_record/railtie.rb +23 -0
- data/lib/active_record/railties/databases.rake +18 -13
- data/lib/active_record/reflection.rb +26 -26
- data/lib/active_record/relation.rb +20 -12
- data/lib/active_record/relation/batches.rb +0 -2
- data/lib/active_record/relation/calculations.rb +11 -5
- data/lib/active_record/relation/finder_methods.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +16 -7
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/session_store.rb +19 -9
- data/lib/active_record/test_case.rb +0 -1
- data/lib/active_record/version.rb +1 -1
- metadata +15 -29
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_support/core_ext/object/blank'
|
2
|
+
require 'active_support/core_ext/module/delegation'
|
2
3
|
|
3
4
|
module ActiveRecord
|
4
5
|
# = Active Record Relation
|
@@ -6,7 +7,7 @@ module ActiveRecord
|
|
6
7
|
JoinOperation = Struct.new(:relation, :join_class, :on)
|
7
8
|
ASSOCIATION_METHODS = [:includes, :eager_load, :preload]
|
8
9
|
MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind]
|
9
|
-
SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :
|
10
|
+
SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order]
|
10
11
|
|
11
12
|
include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches
|
12
13
|
|
@@ -29,6 +30,7 @@ module ActiveRecord
|
|
29
30
|
SINGLE_VALUE_METHODS.each {|v| instance_variable_set(:"@#{v}_value", nil)}
|
30
31
|
(ASSOCIATION_METHODS + MULTI_VALUE_METHODS).each {|v| instance_variable_set(:"@#{v}_values", [])}
|
31
32
|
@extensions = []
|
33
|
+
@create_with_value = {}
|
32
34
|
end
|
33
35
|
|
34
36
|
def insert(values)
|
@@ -214,17 +216,13 @@ module ActiveRecord
|
|
214
216
|
if conditions || options.present?
|
215
217
|
where(conditions).apply_finder_options(options.slice(:limit, :order)).update_all(updates)
|
216
218
|
else
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
limit = arel.limit
|
222
|
-
order = arel.orders
|
219
|
+
stmt = arel.compile_update(Arel.sql(@klass.send(:sanitize_sql_for_assignment, updates)))
|
220
|
+
|
221
|
+
if limit = arel.limit
|
222
|
+
stmt.take limit
|
223
223
|
end
|
224
224
|
|
225
|
-
stmt
|
226
|
-
stmt.take limit if limit
|
227
|
-
stmt.order(*order)
|
225
|
+
stmt.order(*arel.orders)
|
228
226
|
stmt.key = table[primary_key]
|
229
227
|
@klass.connection.update stmt.to_sql, 'SQL', bind_values
|
230
228
|
end
|
@@ -403,11 +401,21 @@ module ActiveRecord
|
|
403
401
|
end
|
404
402
|
|
405
403
|
def scope_for_create
|
406
|
-
@scope_for_create ||= where_values_hash.merge(
|
404
|
+
@scope_for_create ||= where_values_hash.merge(create_with_value)
|
407
405
|
end
|
408
406
|
|
409
407
|
def eager_loading?
|
410
|
-
@should_eager_load ||=
|
408
|
+
@should_eager_load ||=
|
409
|
+
@eager_load_values.any? ||
|
410
|
+
@includes_values.any? && (joined_includes_values.any? || references_eager_loaded_tables?)
|
411
|
+
end
|
412
|
+
|
413
|
+
# Joins that are also marked for preloading. In which case we should just eager load them.
|
414
|
+
# Note that this is a naive implementation because we could have strings and symbols which
|
415
|
+
# represent the same association, but that aren't matched by this. Also, we could have
|
416
|
+
# nested hashes which partially match, e.g. { :a => :b } & { :a => [:b, :c] }
|
417
|
+
def joined_includes_values
|
418
|
+
@includes_values & @joins_values
|
411
419
|
end
|
412
420
|
|
413
421
|
def ==(other)
|
@@ -146,10 +146,16 @@ module ActiveRecord
|
|
146
146
|
if options.except(:distinct).present?
|
147
147
|
apply_finder_options(options.except(:distinct)).calculate(operation, column_name, :distinct => options[:distinct])
|
148
148
|
else
|
149
|
-
|
150
|
-
|
149
|
+
relation = with_default_scope
|
150
|
+
|
151
|
+
if relation.equal?(self)
|
152
|
+
if eager_loading? || (includes_values.present? && references_eager_loaded_tables?)
|
153
|
+
construct_relation_for_association_calculations.calculate(operation, column_name, options)
|
154
|
+
else
|
155
|
+
perform_calculation(operation, column_name, options)
|
156
|
+
end
|
151
157
|
else
|
152
|
-
|
158
|
+
relation.calculate(operation, column_name, options)
|
153
159
|
end
|
154
160
|
end
|
155
161
|
rescue ThrowResult
|
@@ -196,7 +202,7 @@ module ActiveRecord
|
|
196
202
|
|
197
203
|
def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
|
198
204
|
# Postgresql doesn't like ORDER BY when there are no GROUP BY
|
199
|
-
relation =
|
205
|
+
relation = reorder(nil)
|
200
206
|
|
201
207
|
if operation == "count" && (relation.limit_value || relation.offset_value)
|
202
208
|
# Shortcut when limit is zero.
|
@@ -245,7 +251,7 @@ module ActiveRecord
|
|
245
251
|
"#{field} AS #{aliaz}"
|
246
252
|
}
|
247
253
|
|
248
|
-
relation =
|
254
|
+
relation = except(:group).group(group.join(','))
|
249
255
|
relation.select_values = select_values
|
250
256
|
|
251
257
|
calculated_data = @klass.connection.select_all(relation.to_sql)
|
@@ -243,7 +243,7 @@ module ActiveRecord
|
|
243
243
|
end
|
244
244
|
|
245
245
|
def construct_limited_ids_condition(relation)
|
246
|
-
orders = relation.order_values
|
246
|
+
orders = relation.order_values.map { |val| val.presence }.compact
|
247
247
|
values = @klass.connection.distinct("#{@klass.connection.quote_table_name table_name}.#{primary_key}", orders)
|
248
248
|
|
249
249
|
relation = relation.dup
|
@@ -96,11 +96,11 @@ module ActiveRecord
|
|
96
96
|
relation
|
97
97
|
end
|
98
98
|
|
99
|
-
def having(*
|
100
|
-
return self if
|
99
|
+
def having(opts, *rest)
|
100
|
+
return self if opts.blank?
|
101
101
|
|
102
102
|
relation = clone
|
103
|
-
relation.having_values += build_where(
|
103
|
+
relation.having_values += build_where(opts, rest)
|
104
104
|
relation
|
105
105
|
end
|
106
106
|
|
@@ -137,7 +137,7 @@ module ActiveRecord
|
|
137
137
|
|
138
138
|
def create_with(value)
|
139
139
|
relation = clone
|
140
|
-
relation.create_with_value = value
|
140
|
+
relation.create_with_value = value ? create_with_value.merge(value) : {}
|
141
141
|
relation
|
142
142
|
end
|
143
143
|
|
@@ -305,9 +305,18 @@ module ActiveRecord
|
|
305
305
|
def reverse_sql_order(order_query)
|
306
306
|
order_query = ["#{quoted_table_name}.#{quoted_primary_key} ASC"] if order_query.empty?
|
307
307
|
|
308
|
-
order_query.
|
309
|
-
|
310
|
-
|
308
|
+
order_query.map do |o|
|
309
|
+
case o
|
310
|
+
when Arel::Nodes::Ascending, Arel::Nodes::Descending
|
311
|
+
o.reverse
|
312
|
+
when String, Symbol
|
313
|
+
o.to_s.split(',').collect do |s|
|
314
|
+
s.gsub!(/\sasc\Z/i, ' DESC') || s.gsub!(/\sdesc\Z/i, ' ASC') || s.concat(' DESC')
|
315
|
+
end
|
316
|
+
else
|
317
|
+
o
|
318
|
+
end
|
319
|
+
end.flatten
|
311
320
|
end
|
312
321
|
|
313
322
|
def array_of_strings?(o)
|
@@ -55,7 +55,7 @@ module ActiveRecord
|
|
55
55
|
|
56
56
|
merged_relation.lock_value = r.lock_value unless merged_relation.lock_value
|
57
57
|
|
58
|
-
merged_relation = merged_relation.create_with(r.create_with_value)
|
58
|
+
merged_relation = merged_relation.create_with(r.create_with_value) unless r.create_with_value.empty?
|
59
59
|
|
60
60
|
# Apply scope extension modules
|
61
61
|
merged_relation.send :apply_modules, r.extensions
|
@@ -181,11 +181,6 @@ module ActiveRecord
|
|
181
181
|
class SqlBypass
|
182
182
|
extend ClassMethods
|
183
183
|
|
184
|
-
##
|
185
|
-
# :singleton-method:
|
186
|
-
# Use the ActiveRecord::Base.connection by default.
|
187
|
-
cattr_accessor :connection
|
188
|
-
|
189
184
|
##
|
190
185
|
# :singleton-method:
|
191
186
|
# The table name defaults to 'sessions'.
|
@@ -206,10 +201,19 @@ module ActiveRecord
|
|
206
201
|
|
207
202
|
class << self
|
208
203
|
alias :data_column_name :data_column
|
204
|
+
|
205
|
+
# Use the ActiveRecord::Base.connection by default.
|
206
|
+
attr_writer :connection
|
207
|
+
|
208
|
+
# Use the ActiveRecord::Base.connection_pool by default.
|
209
|
+
attr_writer :connection_pool
|
209
210
|
|
210
|
-
remove_method :connection
|
211
211
|
def connection
|
212
|
-
|
212
|
+
@connection ||= ActiveRecord::Base.connection
|
213
|
+
end
|
214
|
+
|
215
|
+
def connection_pool
|
216
|
+
@connection_pool ||= ActiveRecord::Base.connection_pool
|
213
217
|
end
|
214
218
|
|
215
219
|
# Look up a session by id and unmarshal its data if found.
|
@@ -219,6 +223,8 @@ module ActiveRecord
|
|
219
223
|
end
|
220
224
|
end
|
221
225
|
end
|
226
|
+
|
227
|
+
delegate :connection, :connection=, :connection_pool, :connection_pool=, :to => self
|
222
228
|
|
223
229
|
attr_reader :session_id, :new_record
|
224
230
|
alias :new_record? :new_record
|
@@ -297,8 +303,12 @@ module ActiveRecord
|
|
297
303
|
private
|
298
304
|
def get_session(env, sid)
|
299
305
|
Base.silence do
|
300
|
-
sid
|
301
|
-
|
306
|
+
unless sid and session = @@session_class.find_by_session_id(sid)
|
307
|
+
# If the sid was nil or if there is no pre-existing session under the sid,
|
308
|
+
# force the generation of a new sid and associate a new session associated with the new sid
|
309
|
+
sid = generate_sid
|
310
|
+
session = @@session_class.new(:session_id => sid, :data => {})
|
311
|
+
end
|
302
312
|
env[SESSION_RECORD_KEY] = session
|
303
313
|
[sid, session.data]
|
304
314
|
end
|
@@ -46,7 +46,6 @@ module ActiveRecord
|
|
46
46
|
$queries_executed = []
|
47
47
|
yield
|
48
48
|
ensure
|
49
|
-
%w{ BEGIN COMMIT }.each { |x| $queries_executed.delete(x) }
|
50
49
|
assert_equal num, $queries_executed.size, "#{$queries_executed.size} instead of #{num} queries were executed.#{$queries_executed.size == 0 ? '' : "\nQueries:\n#{$queries_executed.join("\n")}"}"
|
51
50
|
end
|
52
51
|
|
metadata
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease: 6
|
4
|
+
prerelease: true
|
6
5
|
segments:
|
7
6
|
- 3
|
8
7
|
- 1
|
9
8
|
- 0
|
10
|
-
-
|
11
|
-
|
12
|
-
version: 3.1.0.rc4
|
9
|
+
- rc5
|
10
|
+
version: 3.1.0.rc5
|
13
11
|
platform: ruby
|
14
12
|
authors:
|
15
13
|
- David Heinemeier Hansson
|
@@ -17,74 +15,65 @@ autorequire:
|
|
17
15
|
bindir: bin
|
18
16
|
cert_chain: []
|
19
17
|
|
20
|
-
date: 2011-
|
18
|
+
date: 2011-07-25 00:00:00 -07:00
|
19
|
+
default_executable:
|
21
20
|
dependencies:
|
22
21
|
- !ruby/object:Gem::Dependency
|
23
22
|
name: activesupport
|
24
23
|
prerelease: false
|
25
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
25
|
requirements:
|
28
26
|
- - "="
|
29
27
|
- !ruby/object:Gem::Version
|
30
|
-
hash: 15424109
|
31
28
|
segments:
|
32
29
|
- 3
|
33
30
|
- 1
|
34
31
|
- 0
|
35
|
-
-
|
36
|
-
|
37
|
-
version: 3.1.0.rc4
|
32
|
+
- rc5
|
33
|
+
version: 3.1.0.rc5
|
38
34
|
type: :runtime
|
39
35
|
version_requirements: *id001
|
40
36
|
- !ruby/object:Gem::Dependency
|
41
37
|
name: activemodel
|
42
38
|
prerelease: false
|
43
39
|
requirement: &id002 !ruby/object:Gem::Requirement
|
44
|
-
none: false
|
45
40
|
requirements:
|
46
41
|
- - "="
|
47
42
|
- !ruby/object:Gem::Version
|
48
|
-
hash: 15424109
|
49
43
|
segments:
|
50
44
|
- 3
|
51
45
|
- 1
|
52
46
|
- 0
|
53
|
-
-
|
54
|
-
|
55
|
-
version: 3.1.0.rc4
|
47
|
+
- rc5
|
48
|
+
version: 3.1.0.rc5
|
56
49
|
type: :runtime
|
57
50
|
version_requirements: *id002
|
58
51
|
- !ruby/object:Gem::Dependency
|
59
52
|
name: arel
|
60
53
|
prerelease: false
|
61
54
|
requirement: &id003 !ruby/object:Gem::Requirement
|
62
|
-
none: false
|
63
55
|
requirements:
|
64
56
|
- - ~>
|
65
57
|
- !ruby/object:Gem::Version
|
66
|
-
hash: 9
|
67
58
|
segments:
|
68
59
|
- 2
|
69
60
|
- 1
|
70
|
-
-
|
71
|
-
version: 2.1.
|
61
|
+
- 4
|
62
|
+
version: 2.1.4
|
72
63
|
type: :runtime
|
73
64
|
version_requirements: *id003
|
74
65
|
- !ruby/object:Gem::Dependency
|
75
66
|
name: tzinfo
|
76
67
|
prerelease: false
|
77
68
|
requirement: &id004 !ruby/object:Gem::Requirement
|
78
|
-
none: false
|
79
69
|
requirements:
|
80
70
|
- - ~>
|
81
71
|
- !ruby/object:Gem::Version
|
82
|
-
hash: 37
|
83
72
|
segments:
|
84
73
|
- 0
|
85
74
|
- 3
|
86
|
-
-
|
87
|
-
version: 0.3.
|
75
|
+
- 29
|
76
|
+
version: 0.3.29
|
88
77
|
type: :runtime
|
89
78
|
version_requirements: *id004
|
90
79
|
description: Databases on Rails. Build a persistent domain model by mapping database tables to Ruby classes. Strong conventions for associations, validations, aggregations, migrations, and testing come baked-in.
|
@@ -223,6 +212,7 @@ files:
|
|
223
212
|
- lib/rails/generators/active_record/session_migration/session_migration_generator.rb
|
224
213
|
- lib/rails/generators/active_record/session_migration/templates/migration.rb
|
225
214
|
- lib/rails/generators/active_record.rb
|
215
|
+
has_rdoc: true
|
226
216
|
homepage: http://www.rubyonrails.org
|
227
217
|
licenses: []
|
228
218
|
|
@@ -233,22 +223,18 @@ rdoc_options:
|
|
233
223
|
require_paths:
|
234
224
|
- lib
|
235
225
|
required_ruby_version: !ruby/object:Gem::Requirement
|
236
|
-
none: false
|
237
226
|
requirements:
|
238
227
|
- - ">="
|
239
228
|
- !ruby/object:Gem::Version
|
240
|
-
hash: 57
|
241
229
|
segments:
|
242
230
|
- 1
|
243
231
|
- 8
|
244
232
|
- 7
|
245
233
|
version: 1.8.7
|
246
234
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
247
|
-
none: false
|
248
235
|
requirements:
|
249
236
|
- - ">"
|
250
237
|
- !ruby/object:Gem::Version
|
251
|
-
hash: 25
|
252
238
|
segments:
|
253
239
|
- 1
|
254
240
|
- 3
|
@@ -257,7 +243,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
257
243
|
requirements: []
|
258
244
|
|
259
245
|
rubyforge_project:
|
260
|
-
rubygems_version: 1.
|
246
|
+
rubygems_version: 1.3.6
|
261
247
|
signing_key:
|
262
248
|
specification_version: 3
|
263
249
|
summary: Object-relational mapper framework (part of Rails).
|