activerecord 3.0.0 → 3.0.2
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 +37 -0
- data/examples/performance.rb +18 -1
- data/lib/active_record.rb +3 -3
- data/lib/active_record/aggregations.rb +2 -2
- data/lib/active_record/association_preload.rb +1 -1
- data/lib/active_record/associations.rb +59 -26
- data/lib/active_record/associations/association_collection.rb +28 -18
- data/lib/active_record/associations/association_proxy.rb +4 -4
- data/lib/active_record/associations/belongs_to_association.rb +3 -3
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +10 -13
- data/lib/active_record/associations/has_many_through_association.rb +2 -3
- data/lib/active_record/associations/has_one_association.rb +6 -6
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/attribute_methods/before_type_cast.rb +1 -4
- data/lib/active_record/attribute_methods/primary_key.rb +4 -3
- data/lib/active_record/autosave_association.rb +7 -7
- data/lib/active_record/base.rb +62 -46
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +6 -8
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +5 -9
- data/lib/active_record/connection_adapters/mysql_adapter.rb +7 -7
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +2 -2
- data/lib/active_record/dynamic_finder_match.rb +20 -17
- data/lib/active_record/dynamic_scope_match.rb +6 -15
- data/lib/active_record/fixtures.rb +3 -5
- data/lib/active_record/locking/optimistic.rb +1 -1
- data/lib/active_record/locking/pessimistic.rb +4 -4
- data/lib/active_record/nested_attributes.rb +17 -13
- data/lib/active_record/persistence.rb +7 -8
- data/lib/active_record/railties/databases.rake +7 -7
- data/lib/active_record/relation.rb +16 -18
- data/lib/active_record/relation/batches.rb +1 -1
- data/lib/active_record/relation/calculations.rb +37 -28
- data/lib/active_record/relation/finder_methods.rb +19 -19
- data/lib/active_record/relation/predicate_builder.rb +3 -1
- data/lib/active_record/relation/query_methods.rb +100 -75
- data/lib/active_record/relation/spawn_methods.rb +50 -39
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/session_store.rb +4 -4
- data/lib/active_record/transactions.rb +6 -6
- data/lib/active_record/validations.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +6 -1
- data/lib/active_record/version.rb +2 -2
- data/lib/rails/generators/active_record.rb +2 -10
- data/lib/rails/generators/active_record/migration.rb +15 -0
- metadata +15 -14
@@ -5,9 +5,11 @@ module ActiveRecord
|
|
5
5
|
def merge(r)
|
6
6
|
merged_relation = clone
|
7
7
|
return merged_relation unless r
|
8
|
+
return to_a & r if r.is_a?(Array)
|
8
9
|
|
9
|
-
|
10
|
+
Relation::ASSOCIATION_METHODS.each do |method|
|
10
11
|
value = r.send(:"#{method}_values")
|
12
|
+
|
11
13
|
unless value.empty?
|
12
14
|
if method == :includes
|
13
15
|
merged_relation = merged_relation.includes(value)
|
@@ -17,26 +19,44 @@ module ActiveRecord
|
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
|
22
|
+
(Relation::MULTI_VALUE_METHODS - [:joins, :where, :order]).each do |method|
|
23
|
+
value = r.send(:"#{method}_values")
|
24
|
+
merged_relation.send(:"#{method}_values=", merged_relation.send(:"#{method}_values") + value) if value.present?
|
25
|
+
end
|
23
26
|
|
24
|
-
r.
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
27
|
+
order_value = r.order_values
|
28
|
+
if order_value.present?
|
29
|
+
if r.reorder_flag
|
30
|
+
merged_relation.order_values = order_value
|
31
|
+
else
|
32
|
+
merged_relation.order_values = merged_relation.order_values + order_value
|
29
33
|
end
|
34
|
+
end
|
30
35
|
|
31
|
-
|
36
|
+
merged_relation = merged_relation.joins(r.joins_values)
|
37
|
+
|
38
|
+
merged_wheres = @where_values + r.where_values
|
39
|
+
|
40
|
+
unless @where_values.empty?
|
41
|
+
# Remove duplicates, last one wins.
|
42
|
+
seen = Hash.new { |h,table| h[table] = {} }
|
43
|
+
merged_wheres = merged_wheres.reverse.reject { |w|
|
44
|
+
nuke = false
|
45
|
+
if w.respond_to?(:operator) && w.operator == :==
|
46
|
+
name = w.left.name
|
47
|
+
table = w.left.relation.name
|
48
|
+
nuke = seen[table][name]
|
49
|
+
seen[table][name] = true
|
50
|
+
end
|
51
|
+
nuke
|
52
|
+
}.reverse
|
32
53
|
end
|
33
54
|
|
34
55
|
merged_relation.where_values = merged_wheres
|
35
56
|
|
36
57
|
Relation::SINGLE_VALUE_METHODS.reject {|m| m == :lock}.each do |method|
|
37
|
-
|
38
|
-
|
39
|
-
end
|
58
|
+
value = r.send(:"#{method}_value")
|
59
|
+
merged_relation.send(:"#{method}_value=", value) unless value.nil?
|
40
60
|
end
|
41
61
|
|
42
62
|
merged_relation.lock_value = r.lock_value unless merged_relation.lock_value
|
@@ -52,12 +72,12 @@ module ActiveRecord
|
|
52
72
|
def except(*skips)
|
53
73
|
result = self.class.new(@klass, table)
|
54
74
|
|
55
|
-
(Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS).each do |method|
|
56
|
-
result.send(:"#{method}_values=", send(:"#{method}_values"))
|
75
|
+
((Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS) - skips).each do |method|
|
76
|
+
result.send(:"#{method}_values=", send(:"#{method}_values"))
|
57
77
|
end
|
58
78
|
|
59
|
-
Relation::SINGLE_VALUE_METHODS.each do |method|
|
60
|
-
result.send(:"#{method}_value=", send(:"#{method}_value"))
|
79
|
+
(Relation::SINGLE_VALUE_METHODS - skips).each do |method|
|
80
|
+
result.send(:"#{method}_value=", send(:"#{method}_value"))
|
61
81
|
end
|
62
82
|
|
63
83
|
result
|
@@ -66,14 +86,12 @@ module ActiveRecord
|
|
66
86
|
def only(*onlies)
|
67
87
|
result = self.class.new(@klass, table)
|
68
88
|
|
69
|
-
onlies.each do |
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
raise "Invalid argument : #{only}"
|
76
|
-
end
|
89
|
+
((Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS) & onlies).each do |method|
|
90
|
+
result.send(:"#{method}_values=", send(:"#{method}_values"))
|
91
|
+
end
|
92
|
+
|
93
|
+
(Relation::SINGLE_VALUE_METHODS & onlies).each do |method|
|
94
|
+
result.send(:"#{method}_value=", send(:"#{method}_value"))
|
77
95
|
end
|
78
96
|
|
79
97
|
result
|
@@ -87,23 +105,16 @@ module ActiveRecord
|
|
87
105
|
return relation unless options
|
88
106
|
|
89
107
|
options.assert_valid_keys(VALID_FIND_OPTIONS)
|
108
|
+
finders = options.dup
|
109
|
+
finders.delete_if { |key, value| value.nil? }
|
90
110
|
|
91
|
-
[:joins, :select, :group, :having, :limit, :offset, :from, :lock].each do |finder|
|
92
|
-
|
93
|
-
relation = relation.send(finder, value)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
relation = relation.readonly(options[:readonly]) if options.key? :readonly
|
98
|
-
|
99
|
-
# Give precedence to newly-applied orders and groups to play nicely with with_scope
|
100
|
-
[:group, :order].each do |finder|
|
101
|
-
relation.send("#{finder}_values=", Array.wrap(options[finder]) + relation.send("#{finder}_values")) if options.has_key?(finder)
|
111
|
+
([:joins, :select, :group, :order, :having, :limit, :offset, :from, :lock, :readonly] & finders.keys).each do |finder|
|
112
|
+
relation = relation.send(finder, finders[finder])
|
102
113
|
end
|
103
114
|
|
104
|
-
relation = relation.where(
|
105
|
-
relation = relation.includes(
|
106
|
-
relation = relation.extending(
|
115
|
+
relation = relation.where(finders[:conditions]) if options.has_key?(:conditions)
|
116
|
+
relation = relation.includes(finders[:include]) if options.has_key?(:include)
|
117
|
+
relation = relation.extending(finders[:extend]) if options.has_key?(:extend)
|
107
118
|
|
108
119
|
relation
|
109
120
|
end
|
@@ -5,7 +5,7 @@ module ActiveRecord #:nodoc:
|
|
5
5
|
include ActiveModel::Serializers::JSON
|
6
6
|
|
7
7
|
def serializable_hash(options = nil)
|
8
|
-
options
|
8
|
+
options = options.try(:clone) || {}
|
9
9
|
|
10
10
|
options[:except] = Array.wrap(options[:except]).map { |n| n.to_s }
|
11
11
|
options[:except] |= Array.wrap(self.class.inheritance_column)
|
@@ -228,7 +228,7 @@ module ActiveRecord
|
|
228
228
|
@session_id = attributes[:session_id]
|
229
229
|
@data = attributes[:data]
|
230
230
|
@marshaled_data = attributes[:marshaled_data]
|
231
|
-
@
|
231
|
+
@persisted = !@marshaled_data.nil?
|
232
232
|
end
|
233
233
|
|
234
234
|
# Lazy-unmarshal session state.
|
@@ -252,8 +252,8 @@ module ActiveRecord
|
|
252
252
|
marshaled_data = self.class.marshal(data)
|
253
253
|
connect = connection
|
254
254
|
|
255
|
-
|
256
|
-
@
|
255
|
+
unless @persisted
|
256
|
+
@persisted = true
|
257
257
|
connect.update <<-end_sql, 'Create session'
|
258
258
|
INSERT INTO #{table_name} (
|
259
259
|
#{connect.quote_column_name(session_id_column)},
|
@@ -272,7 +272,7 @@ module ActiveRecord
|
|
272
272
|
end
|
273
273
|
|
274
274
|
def destroy
|
275
|
-
return
|
275
|
+
return unless @persisted
|
276
276
|
|
277
277
|
connect = connection
|
278
278
|
connect.delete <<-end_sql, 'Destroy session'
|
@@ -242,7 +242,7 @@ module ActiveRecord
|
|
242
242
|
with_transaction_returning_status { super }
|
243
243
|
end
|
244
244
|
|
245
|
-
# Reset id and @
|
245
|
+
# Reset id and @persisted if the transaction rolls back.
|
246
246
|
def rollback_active_record_state!
|
247
247
|
remember_transaction_record_state
|
248
248
|
yield
|
@@ -297,9 +297,9 @@ module ActiveRecord
|
|
297
297
|
# Save the new record state and id of a record so it can be restored later if a transaction fails.
|
298
298
|
def remember_transaction_record_state #:nodoc
|
299
299
|
@_start_transaction_state ||= {}
|
300
|
-
unless @_start_transaction_state.include?(:
|
300
|
+
unless @_start_transaction_state.include?(:persisted)
|
301
301
|
@_start_transaction_state[:id] = id if has_attribute?(self.class.primary_key)
|
302
|
-
@_start_transaction_state[:
|
302
|
+
@_start_transaction_state[:persisted] = @persisted
|
303
303
|
end
|
304
304
|
unless @_start_transaction_state.include?(:destroyed)
|
305
305
|
@_start_transaction_state[:destroyed] = @destroyed
|
@@ -323,7 +323,7 @@ module ActiveRecord
|
|
323
323
|
restore_state = remove_instance_variable(:@_start_transaction_state)
|
324
324
|
if restore_state
|
325
325
|
@attributes = @attributes.dup if @attributes.frozen?
|
326
|
-
@
|
326
|
+
@persisted = restore_state[:persisted]
|
327
327
|
@destroyed = restore_state[:destroyed]
|
328
328
|
if restore_state[:id]
|
329
329
|
self.id = restore_state[:id]
|
@@ -345,11 +345,11 @@ module ActiveRecord
|
|
345
345
|
def transaction_include_action?(action) #:nodoc
|
346
346
|
case action
|
347
347
|
when :create
|
348
|
-
transaction_record_state(:new_record)
|
348
|
+
transaction_record_state(:new_record) || !transaction_record_state(:persisted)
|
349
349
|
when :destroy
|
350
350
|
destroyed?
|
351
351
|
when :update
|
352
|
-
!(transaction_record_state(:new_record) || destroyed?)
|
352
|
+
!(transaction_record_state(:new_record) || !transaction_record_state(:persisted) || destroyed?)
|
353
353
|
end
|
354
354
|
end
|
355
355
|
end
|
@@ -51,7 +51,7 @@ module ActiveRecord
|
|
51
51
|
|
52
52
|
# Runs all the specified validations and returns true if no errors were added otherwise false.
|
53
53
|
def valid?(context = nil)
|
54
|
-
context ||= (
|
54
|
+
context ||= (persisted? ? :update : :create)
|
55
55
|
output = super(context)
|
56
56
|
|
57
57
|
deprecated_callback_method(:validate)
|
@@ -17,6 +17,11 @@ module ActiveRecord
|
|
17
17
|
table = finder_class.unscoped
|
18
18
|
|
19
19
|
table_name = record.class.quoted_table_name
|
20
|
+
|
21
|
+
if value && record.class.serialized_attributes.key?(attribute.to_s)
|
22
|
+
value = YAML.dump value
|
23
|
+
end
|
24
|
+
|
20
25
|
sql, params = mount_sql_and_params(finder_class, table_name, attribute, value)
|
21
26
|
|
22
27
|
relation = table.where(sql, *params)
|
@@ -26,7 +31,7 @@ module ActiveRecord
|
|
26
31
|
relation = relation.where(scope_item => scope_value)
|
27
32
|
end
|
28
33
|
|
29
|
-
|
34
|
+
if record.persisted?
|
30
35
|
# TODO : This should be in Arel
|
31
36
|
relation = relation.where("#{record.class.quoted_table_name}.#{record.class.primary_key} <> ?", record.send(:id))
|
32
37
|
end
|
@@ -1,27 +1,19 @@
|
|
1
1
|
require 'rails/generators/named_base'
|
2
2
|
require 'rails/generators/migration'
|
3
3
|
require 'rails/generators/active_model'
|
4
|
+
require 'rails/generators/active_record/migration'
|
4
5
|
require 'active_record'
|
5
6
|
|
6
7
|
module ActiveRecord
|
7
8
|
module Generators
|
8
9
|
class Base < Rails::Generators::NamedBase #:nodoc:
|
9
10
|
include Rails::Generators::Migration
|
11
|
+
extend ActiveRecord::Generators::Migration
|
10
12
|
|
11
13
|
# Set the current directory as base for the inherited generators.
|
12
14
|
def self.base_root
|
13
15
|
File.dirname(__FILE__)
|
14
16
|
end
|
15
|
-
|
16
|
-
# Implement the required interface for Rails::Generators::Migration.
|
17
|
-
def self.next_migration_number(dirname) #:nodoc:
|
18
|
-
next_migration_number = current_migration_number(dirname) + 1
|
19
|
-
if ActiveRecord::Base.timestamped_migrations
|
20
|
-
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
|
21
|
-
else
|
22
|
-
"%.3d" % next_migration_number
|
23
|
-
end
|
24
|
-
end
|
25
17
|
end
|
26
18
|
end
|
27
19
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Generators
|
3
|
+
module Migration
|
4
|
+
# Implement the required interface for Rails::Generators::Migration.
|
5
|
+
def next_migration_number(dirname) #:nodoc:
|
6
|
+
next_migration_number = current_migration_number(dirname) + 1
|
7
|
+
if ActiveRecord::Base.timestamped_migrations
|
8
|
+
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
|
9
|
+
else
|
10
|
+
"%.3d" % next_migration_number
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 3
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 3.0.
|
9
|
+
- 2
|
10
|
+
version: 3.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- David Heinemeier Hansson
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-11-15 00:00:00 -06:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -26,12 +26,12 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - "="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
hash:
|
29
|
+
hash: 3
|
30
30
|
segments:
|
31
31
|
- 3
|
32
32
|
- 0
|
33
|
-
-
|
34
|
-
version: 3.0.
|
33
|
+
- 2
|
34
|
+
version: 3.0.2
|
35
35
|
type: :runtime
|
36
36
|
version_requirements: *id001
|
37
37
|
- !ruby/object:Gem::Dependency
|
@@ -42,12 +42,12 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - "="
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
hash:
|
45
|
+
hash: 3
|
46
46
|
segments:
|
47
47
|
- 3
|
48
48
|
- 0
|
49
|
-
-
|
50
|
-
version: 3.0.
|
49
|
+
- 2
|
50
|
+
version: 3.0.2
|
51
51
|
type: :runtime
|
52
52
|
version_requirements: *id002
|
53
53
|
- !ruby/object:Gem::Dependency
|
@@ -58,12 +58,12 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
hash:
|
61
|
+
hash: 11
|
62
62
|
segments:
|
63
|
-
-
|
64
|
-
- 0
|
63
|
+
- 2
|
65
64
|
- 0
|
66
|
-
|
65
|
+
- 2
|
66
|
+
version: 2.0.2
|
67
67
|
type: :runtime
|
68
68
|
version_requirements: *id003
|
69
69
|
- !ruby/object:Gem::Dependency
|
@@ -174,6 +174,7 @@ files:
|
|
174
174
|
- lib/active_record.rb
|
175
175
|
- lib/rails/generators/active_record/migration/migration_generator.rb
|
176
176
|
- lib/rails/generators/active_record/migration/templates/migration.rb
|
177
|
+
- lib/rails/generators/active_record/migration.rb
|
177
178
|
- lib/rails/generators/active_record/model/model_generator.rb
|
178
179
|
- lib/rails/generators/active_record/model/templates/migration.rb
|
179
180
|
- lib/rails/generators/active_record/model/templates/model.rb
|