activerecord 3.2.22.4 → 4.0.13
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 +2799 -617
- data/MIT-LICENSE +1 -1
- data/README.rdoc +23 -32
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +40 -34
- data/lib/active_record/association_relation.rb +22 -0
- data/lib/active_record/associations/alias_tracker.rb +4 -2
- data/lib/active_record/associations/association.rb +60 -46
- data/lib/active_record/associations/association_scope.rb +46 -40
- data/lib/active_record/associations/belongs_to_association.rb +17 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
- data/lib/active_record/associations/builder/association.rb +81 -28
- data/lib/active_record/associations/builder/belongs_to.rb +73 -56
- data/lib/active_record/associations/builder/collection_association.rb +54 -40
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +23 -41
- data/lib/active_record/associations/builder/has_many.rb +8 -64
- data/lib/active_record/associations/builder/has_one.rb +13 -50
- data/lib/active_record/associations/builder/singular_association.rb +13 -13
- data/lib/active_record/associations/collection_association.rb +130 -96
- data/lib/active_record/associations/collection_proxy.rb +916 -63
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +15 -13
- data/lib/active_record/associations/has_many_association.rb +35 -8
- data/lib/active_record/associations/has_many_through_association.rb +37 -17
- data/lib/active_record/associations/has_one_association.rb +42 -19
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +39 -22
- data/lib/active_record/associations/join_dependency/join_base.rb +2 -2
- data/lib/active_record/associations/join_dependency/join_part.rb +21 -8
- data/lib/active_record/associations/join_dependency.rb +30 -9
- data/lib/active_record/associations/join_helper.rb +1 -11
- data/lib/active_record/associations/preloader/association.rb +29 -33
- data/lib/active_record/associations/preloader/collection_association.rb +1 -1
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +2 -2
- data/lib/active_record/associations/preloader/has_many_through.rb +6 -2
- data/lib/active_record/associations/preloader/has_one.rb +1 -1
- data/lib/active_record/associations/preloader/through_association.rb +13 -17
- data/lib/active_record/associations/preloader.rb +20 -43
- data/lib/active_record/associations/singular_association.rb +11 -11
- data/lib/active_record/associations/through_association.rb +3 -3
- data/lib/active_record/associations.rb +223 -282
- data/lib/active_record/attribute_assignment.rb +134 -154
- data/lib/active_record/attribute_methods/before_type_cast.rb +44 -5
- data/lib/active_record/attribute_methods/dirty.rb +36 -29
- data/lib/active_record/attribute_methods/primary_key.rb +45 -31
- data/lib/active_record/attribute_methods/query.rb +5 -4
- data/lib/active_record/attribute_methods/read.rb +67 -90
- data/lib/active_record/attribute_methods/serialization.rb +133 -70
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +51 -45
- data/lib/active_record/attribute_methods/write.rb +34 -39
- data/lib/active_record/attribute_methods.rb +268 -108
- data/lib/active_record/autosave_association.rb +80 -73
- data/lib/active_record/base.rb +54 -451
- data/lib/active_record/callbacks.rb +60 -22
- data/lib/active_record/coders/yaml_column.rb +18 -21
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +347 -197
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +146 -138
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +25 -19
- data/lib/active_record/connection_adapters/abstract/quoting.rb +19 -3
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +151 -142
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +499 -217
- data/lib/active_record/connection_adapters/abstract/transaction.rb +208 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +209 -44
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +169 -61
- data/lib/active_record/connection_adapters/column.rb +67 -36
- data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +28 -29
- data/lib/active_record/connection_adapters/mysql_adapter.rb +200 -73
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +98 -0
- data/lib/active_record/connection_adapters/postgresql/cast.rb +160 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +240 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +374 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +183 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +508 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +544 -899
- data/lib/active_record/connection_adapters/schema_cache.rb +76 -16
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +595 -16
- data/lib/active_record/connection_handling.rb +98 -0
- data/lib/active_record/core.rb +472 -0
- data/lib/active_record/counter_cache.rb +107 -108
- data/lib/active_record/dynamic_matchers.rb +115 -63
- data/lib/active_record/errors.rb +36 -18
- data/lib/active_record/explain.rb +15 -63
- data/lib/active_record/explain_registry.rb +30 -0
- data/lib/active_record/explain_subscriber.rb +8 -4
- data/lib/active_record/fixture_set/file.rb +55 -0
- data/lib/active_record/fixtures.rb +159 -155
- data/lib/active_record/inheritance.rb +93 -59
- data/lib/active_record/integration.rb +8 -8
- data/lib/active_record/locale/en.yml +8 -1
- data/lib/active_record/locking/optimistic.rb +39 -43
- data/lib/active_record/locking/pessimistic.rb +4 -4
- data/lib/active_record/log_subscriber.rb +19 -9
- data/lib/active_record/migration/command_recorder.rb +102 -33
- data/lib/active_record/migration/join_table.rb +15 -0
- data/lib/active_record/migration.rb +411 -173
- data/lib/active_record/model_schema.rb +81 -94
- data/lib/active_record/nested_attributes.rb +173 -131
- data/lib/active_record/null_relation.rb +67 -0
- data/lib/active_record/persistence.rb +254 -106
- data/lib/active_record/query_cache.rb +18 -36
- data/lib/active_record/querying.rb +19 -15
- data/lib/active_record/railtie.rb +113 -38
- data/lib/active_record/railties/console_sandbox.rb +3 -4
- data/lib/active_record/railties/controller_runtime.rb +4 -3
- data/lib/active_record/railties/databases.rake +115 -368
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +7 -3
- data/lib/active_record/reflection.rb +110 -61
- data/lib/active_record/relation/batches.rb +29 -29
- data/lib/active_record/relation/calculations.rb +155 -125
- data/lib/active_record/relation/delegation.rb +94 -18
- data/lib/active_record/relation/finder_methods.rb +151 -203
- data/lib/active_record/relation/merger.rb +188 -0
- data/lib/active_record/relation/predicate_builder.rb +85 -42
- data/lib/active_record/relation/query_methods.rb +793 -146
- data/lib/active_record/relation/spawn_methods.rb +43 -150
- data/lib/active_record/relation.rb +293 -173
- data/lib/active_record/result.rb +48 -7
- data/lib/active_record/runtime_registry.rb +17 -0
- data/lib/active_record/sanitization.rb +41 -54
- data/lib/active_record/schema.rb +19 -12
- data/lib/active_record/schema_dumper.rb +41 -41
- data/lib/active_record/schema_migration.rb +46 -0
- data/lib/active_record/scoping/default.rb +56 -52
- data/lib/active_record/scoping/named.rb +78 -103
- data/lib/active_record/scoping.rb +54 -124
- data/lib/active_record/serialization.rb +6 -2
- data/lib/active_record/serializers/xml_serializer.rb +9 -15
- data/lib/active_record/statement_cache.rb +26 -0
- data/lib/active_record/store.rb +131 -15
- data/lib/active_record/tasks/database_tasks.rb +204 -0
- data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +144 -0
- data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
- data/lib/active_record/test_case.rb +67 -38
- data/lib/active_record/timestamp.rb +16 -11
- data/lib/active_record/transactions.rb +73 -51
- data/lib/active_record/validations/associated.rb +19 -13
- data/lib/active_record/validations/presence.rb +65 -0
- data/lib/active_record/validations/uniqueness.rb +110 -57
- data/lib/active_record/validations.rb +18 -17
- data/lib/active_record/version.rb +7 -6
- data/lib/active_record.rb +63 -45
- data/lib/rails/generators/active_record/migration/migration_generator.rb +45 -8
- data/lib/rails/generators/active_record/{model/templates/migration.rb → migration/templates/create_table_migration.rb} +4 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +20 -15
- data/lib/rails/generators/active_record/model/model_generator.rb +5 -4
- data/lib/rails/generators/active_record/model/templates/model.rb +4 -6
- data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
- data/lib/rails/generators/active_record.rb +3 -5
- metadata +43 -29
- data/examples/associations.png +0 -0
- data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
- data/lib/active_record/dynamic_finder_match.rb +0 -68
- data/lib/active_record/dynamic_scope_match.rb +0 -23
- data/lib/active_record/fixtures/file.rb +0 -65
- data/lib/active_record/identity_map.rb +0 -162
- data/lib/active_record/observer.rb +0 -121
- data/lib/active_record/session_store.rb +0 -360
- data/lib/rails/generators/active_record/migration.rb +0 -15
- data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
- data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -2,16 +2,16 @@ module ActiveRecord
|
|
2
2
|
module Associations
|
3
3
|
class Preloader
|
4
4
|
class Association #:nodoc:
|
5
|
-
attr_reader :owners, :reflection, :
|
6
|
-
|
7
|
-
def initialize(klass, owners, reflection,
|
8
|
-
@klass
|
9
|
-
@owners
|
10
|
-
@reflection
|
11
|
-
@
|
12
|
-
@model
|
13
|
-
@
|
14
|
-
@owners_by_key
|
5
|
+
attr_reader :owners, :reflection, :preload_scope, :model, :klass
|
6
|
+
|
7
|
+
def initialize(klass, owners, reflection, preload_scope)
|
8
|
+
@klass = klass
|
9
|
+
@owners = owners
|
10
|
+
@reflection = reflection
|
11
|
+
@preload_scope = preload_scope
|
12
|
+
@model = owners.first && owners.first.class
|
13
|
+
@scope = nil
|
14
|
+
@owners_by_key = nil
|
15
15
|
end
|
16
16
|
|
17
17
|
def run
|
@@ -24,12 +24,12 @@ module ActiveRecord
|
|
24
24
|
raise NotImplementedError
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
28
|
-
@
|
27
|
+
def scope
|
28
|
+
@scope ||= build_scope
|
29
29
|
end
|
30
30
|
|
31
31
|
def records_for(ids)
|
32
|
-
|
32
|
+
scope.where(association_key.in(ids))
|
33
33
|
end
|
34
34
|
|
35
35
|
def table
|
@@ -76,8 +76,8 @@ module ActiveRecord
|
|
76
76
|
else
|
77
77
|
# Some databases impose a limit on the number of ids in a list (in Oracle it's 1000)
|
78
78
|
# Make several smaller queries if necessary or make one query if the adapter supports it
|
79
|
-
sliced = owner_keys.each_slice(
|
80
|
-
records = sliced.map { |slice| records_for(slice) }.flatten
|
79
|
+
sliced = owner_keys.each_slice(klass.connection.in_clause_length || owner_keys.size)
|
80
|
+
records = sliced.map { |slice| records_for(slice).to_a }.flatten
|
81
81
|
end
|
82
82
|
|
83
83
|
# Each record may have multiple owners, and vice-versa
|
@@ -92,33 +92,29 @@ module ActiveRecord
|
|
92
92
|
records_by_owner
|
93
93
|
end
|
94
94
|
|
95
|
+
def reflection_scope
|
96
|
+
@reflection_scope ||= reflection.scope ? klass.unscoped.instance_exec(nil, &reflection.scope) : klass.unscoped
|
97
|
+
end
|
98
|
+
|
95
99
|
def build_scope
|
96
|
-
scope = klass.
|
100
|
+
scope = klass.unscoped
|
101
|
+
scope.default_scoped = true
|
97
102
|
|
98
|
-
|
99
|
-
|
103
|
+
values = reflection_scope.values
|
104
|
+
preload_values = preload_scope.values
|
100
105
|
|
101
|
-
scope
|
102
|
-
scope =
|
106
|
+
scope.where_values = Array(values[:where]) + Array(preload_values[:where])
|
107
|
+
scope.references_values = Array(values[:references]) + Array(preload_values[:references])
|
108
|
+
|
109
|
+
scope._select! preload_values[:select] || values[:select] || table[Arel.star]
|
110
|
+
scope.includes! preload_values[:includes] || values[:includes]
|
103
111
|
|
104
112
|
if options[:as]
|
105
|
-
scope
|
106
|
-
klass.table_name => {
|
107
|
-
reflection.type => model.base_class.sti_name
|
108
|
-
}
|
109
|
-
)
|
113
|
+
scope.where!(klass.table_name => { reflection.type => model.base_class.sti_name })
|
110
114
|
end
|
111
115
|
|
112
116
|
scope
|
113
117
|
end
|
114
|
-
|
115
|
-
def process_conditions(conditions)
|
116
|
-
if conditions.respond_to?(:to_proc)
|
117
|
-
conditions = klass.send(:instance_eval, &conditions)
|
118
|
-
end
|
119
|
-
|
120
|
-
conditions
|
121
|
-
end
|
122
118
|
end
|
123
119
|
end
|
124
120
|
end
|
@@ -6,7 +6,7 @@ module ActiveRecord
|
|
6
6
|
|
7
7
|
def initialize(klass, records, reflection, preload_options)
|
8
8
|
super
|
9
|
-
@join_table = Arel::Table.new(
|
9
|
+
@join_table = Arel::Table.new(reflection.join_table).alias('t0')
|
10
10
|
end
|
11
11
|
|
12
12
|
# Unlike the other associations, we want to get a raw array of rows so that we can
|
@@ -35,7 +35,7 @@ module ActiveRecord
|
|
35
35
|
# record
|
36
36
|
def associated_records_by_owner
|
37
37
|
records = {}
|
38
|
-
super.
|
38
|
+
super.each_value do |rows|
|
39
39
|
rows.map! { |row| records[row[klass.primary_key]] ||= klass.instantiate(row) }
|
40
40
|
end
|
41
41
|
end
|
@@ -5,9 +5,13 @@ module ActiveRecord
|
|
5
5
|
include ThroughAssociation
|
6
6
|
|
7
7
|
def associated_records_by_owner
|
8
|
-
|
9
|
-
|
8
|
+
records_by_owner = super
|
9
|
+
|
10
|
+
if reflection_scope.distinct_value
|
11
|
+
records_by_owner.each_value { |records| records.uniq! }
|
10
12
|
end
|
13
|
+
|
14
|
+
records_by_owner
|
11
15
|
end
|
12
16
|
end
|
13
17
|
end
|
@@ -14,10 +14,7 @@ module ActiveRecord
|
|
14
14
|
def associated_records_by_owner
|
15
15
|
through_records = through_records_by_owner
|
16
16
|
|
17
|
-
|
18
|
-
through_records.values.flatten,
|
19
|
-
source_reflection.name, options
|
20
|
-
).run
|
17
|
+
Preloader.new(through_records.values.flatten, source_reflection.name, reflection_scope).run
|
21
18
|
|
22
19
|
through_records.each do |owner, records|
|
23
20
|
records.map! { |r| r.send(source_reflection.name) }.flatten!
|
@@ -28,16 +25,13 @@ module ActiveRecord
|
|
28
25
|
private
|
29
26
|
|
30
27
|
def through_records_by_owner
|
31
|
-
|
32
|
-
owners, through_reflection.name,
|
33
|
-
through_options
|
34
|
-
).run
|
28
|
+
Preloader.new(owners, through_reflection.name, through_scope).run
|
35
29
|
|
36
30
|
Hash[owners.map do |owner|
|
37
31
|
through_records = Array.wrap(owner.send(through_reflection.name))
|
38
32
|
|
39
33
|
# Dont cache the association - we would only be caching a subset
|
40
|
-
if (
|
34
|
+
if (through_scope != through_reflection.klass.unscoped) ||
|
41
35
|
(reflection.options[:source_type] && through_reflection.collection?)
|
42
36
|
owner.association(through_reflection.name).reset
|
43
37
|
end
|
@@ -46,20 +40,22 @@ module ActiveRecord
|
|
46
40
|
end]
|
47
41
|
end
|
48
42
|
|
49
|
-
def
|
50
|
-
|
43
|
+
def through_scope
|
44
|
+
through_scope = through_reflection.klass.unscoped
|
51
45
|
|
52
46
|
if options[:source_type]
|
53
|
-
|
47
|
+
through_scope.where! reflection.foreign_type => options[:source_type]
|
54
48
|
else
|
55
|
-
|
56
|
-
|
57
|
-
|
49
|
+
unless reflection_scope.where_values.empty?
|
50
|
+
through_scope.includes_values = Array(reflection_scope.values[:includes] || options[:source])
|
51
|
+
through_scope.where_values = reflection_scope.values[:where]
|
58
52
|
end
|
59
|
-
|
53
|
+
|
54
|
+
through_scope.references! reflection_scope.values[:references]
|
55
|
+
through_scope.order! reflection_scope.values[:order] if through_scope.eager_loading?
|
60
56
|
end
|
61
57
|
|
62
|
-
|
58
|
+
through_scope
|
63
59
|
end
|
64
60
|
end
|
65
61
|
end
|
@@ -12,7 +12,7 @@ module ActiveRecord
|
|
12
12
|
# and all of its books via a single query:
|
13
13
|
#
|
14
14
|
# SELECT * FROM authors
|
15
|
-
# LEFT OUTER JOIN books ON authors.id = books.
|
15
|
+
# LEFT OUTER JOIN books ON authors.id = books.author_id
|
16
16
|
# WHERE authors.name = 'Ken Akamatsu'
|
17
17
|
#
|
18
18
|
# However, this could result in many rows that contain redundant data. After
|
@@ -46,7 +46,7 @@ module ActiveRecord
|
|
46
46
|
autoload :BelongsTo, 'active_record/associations/preloader/belongs_to'
|
47
47
|
end
|
48
48
|
|
49
|
-
attr_reader :records, :associations, :
|
49
|
+
attr_reader :records, :associations, :preload_scope, :model
|
50
50
|
|
51
51
|
# Eager loads the named associations for the given Active Record record(s).
|
52
52
|
#
|
@@ -72,7 +72,7 @@ module ActiveRecord
|
|
72
72
|
# books.
|
73
73
|
# - a Hash which specifies multiple association names, as well as
|
74
74
|
# association names for the to-be-preloaded association objects. For
|
75
|
-
# example, specifying <tt>{ :
|
75
|
+
# example, specifying <tt>{ author: :avatar }</tt> will preload a
|
76
76
|
# book's author, as well as that author's avatar.
|
77
77
|
#
|
78
78
|
# +:associations+ has the same format as the +:include+ option for
|
@@ -80,17 +80,12 @@ module ActiveRecord
|
|
80
80
|
#
|
81
81
|
# :books
|
82
82
|
# [ :books, :author ]
|
83
|
-
# { :
|
84
|
-
# [ :books, { :
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
# to the child associations when +associations+ is a Hash.
|
90
|
-
def initialize(records, associations, options = {})
|
91
|
-
@records = Array.wrap(records).compact.uniq
|
92
|
-
@associations = Array.wrap(associations)
|
93
|
-
@options = options
|
83
|
+
# { author: :avatar }
|
84
|
+
# [ :books, { author: :avatar } ]
|
85
|
+
def initialize(records, associations, preload_scope = nil)
|
86
|
+
@records = Array.wrap(records).compact.uniq
|
87
|
+
@associations = Array.wrap(associations)
|
88
|
+
@preload_scope = preload_scope || Relation.new(nil, nil)
|
94
89
|
end
|
95
90
|
|
96
91
|
def run
|
@@ -105,7 +100,9 @@ module ActiveRecord
|
|
105
100
|
case association
|
106
101
|
when Hash
|
107
102
|
preload_hash(association)
|
108
|
-
when
|
103
|
+
when Symbol
|
104
|
+
preload_one(association)
|
105
|
+
when String
|
109
106
|
preload_one(association.to_sym)
|
110
107
|
else
|
111
108
|
raise ArgumentError, "#{association.inspect} was not recognised for preload"
|
@@ -114,7 +111,7 @@ module ActiveRecord
|
|
114
111
|
|
115
112
|
def preload_hash(association)
|
116
113
|
association.each do |parent, child|
|
117
|
-
Preloader.new(records, parent,
|
114
|
+
Preloader.new(records, parent, preload_scope).run
|
118
115
|
Preloader.new(records.map { |record| record.send(parent) }.flatten, child).run
|
119
116
|
end
|
120
117
|
end
|
@@ -129,39 +126,19 @@ module ActiveRecord
|
|
129
126
|
def preload_one(association)
|
130
127
|
grouped_records(association).each do |reflection, klasses|
|
131
128
|
klasses.each do |klass, records|
|
132
|
-
preloader_for(reflection).new(klass, records, reflection,
|
129
|
+
preloader_for(reflection).new(klass, records, reflection, preload_scope).run
|
133
130
|
end
|
134
131
|
end
|
135
132
|
end
|
136
133
|
|
137
134
|
def grouped_records(association)
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
end
|
144
|
-
|
145
|
-
def records_by_reflection(association)
|
146
|
-
records.group_by do |record|
|
147
|
-
reflection = record.class.reflections[association]
|
148
|
-
|
149
|
-
unless reflection
|
150
|
-
raise ActiveRecord::ConfigurationError, "Association named '#{association}' was not found; " \
|
151
|
-
"perhaps you misspelled it?"
|
152
|
-
end
|
153
|
-
|
154
|
-
reflection
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
def association_klass(reflection, record)
|
159
|
-
if reflection.macro == :belongs_to && reflection.options[:polymorphic]
|
160
|
-
klass = record.send(reflection.foreign_type)
|
161
|
-
klass && klass.constantize
|
162
|
-
else
|
163
|
-
reflection.klass
|
135
|
+
h = {}
|
136
|
+
records.each do |record|
|
137
|
+
assoc = record.association(association)
|
138
|
+
klasses = h[assoc.reflection] ||= {}
|
139
|
+
(klasses[assoc.klass] ||= []) << record
|
164
140
|
end
|
141
|
+
h
|
165
142
|
end
|
166
143
|
|
167
144
|
def preloader_for(reflection)
|
@@ -12,21 +12,21 @@ module ActiveRecord
|
|
12
12
|
target
|
13
13
|
end
|
14
14
|
|
15
|
-
# Implements the writer method, e.g. foo.
|
15
|
+
# Implements the writer method, e.g. foo.bar= for Foo.belongs_to :bar
|
16
16
|
def writer(record)
|
17
17
|
replace(record)
|
18
18
|
end
|
19
19
|
|
20
|
-
def create(attributes = {},
|
21
|
-
|
20
|
+
def create(attributes = {}, &block)
|
21
|
+
_create_record(attributes, &block)
|
22
22
|
end
|
23
23
|
|
24
|
-
def create!(attributes = {},
|
25
|
-
|
24
|
+
def create!(attributes = {}, &block)
|
25
|
+
_create_record(attributes, true, &block)
|
26
26
|
end
|
27
27
|
|
28
|
-
def build(attributes = {}
|
29
|
-
record = build_record(attributes
|
28
|
+
def build(attributes = {})
|
29
|
+
record = build_record(attributes)
|
30
30
|
yield(record) if block_given?
|
31
31
|
set_new_record(record)
|
32
32
|
record
|
@@ -35,11 +35,11 @@ module ActiveRecord
|
|
35
35
|
private
|
36
36
|
|
37
37
|
def create_scope
|
38
|
-
|
38
|
+
scope.scope_for_create.stringify_keys.except(klass.primary_key)
|
39
39
|
end
|
40
40
|
|
41
41
|
def find_target
|
42
|
-
|
42
|
+
scope.take.tap { |record| set_inverse_instance(record) }
|
43
43
|
end
|
44
44
|
|
45
45
|
# Implemented by subclasses
|
@@ -51,8 +51,8 @@ module ActiveRecord
|
|
51
51
|
replace(record)
|
52
52
|
end
|
53
53
|
|
54
|
-
def
|
55
|
-
record = build_record(attributes
|
54
|
+
def _create_record(attributes, raise_error = false)
|
55
|
+
record = build_record(attributes)
|
56
56
|
yield(record) if block_given?
|
57
57
|
saved = record.save
|
58
58
|
set_new_record(record)
|
@@ -14,8 +14,8 @@ module ActiveRecord
|
|
14
14
|
def target_scope
|
15
15
|
scope = super
|
16
16
|
chain[1..-1].each do |reflection|
|
17
|
-
scope
|
18
|
-
reflection.klass.
|
17
|
+
scope.merge!(
|
18
|
+
reflection.klass.all.with_default_scope.
|
19
19
|
except(:select, :create_with, :includes, :preload, :joins, :eager_load)
|
20
20
|
)
|
21
21
|
end
|
@@ -28,7 +28,7 @@ module ActiveRecord
|
|
28
28
|
# methods which create and delete records on the association.
|
29
29
|
#
|
30
30
|
# We only support indirectly modifying through associations which has a belongs_to source.
|
31
|
-
# This is the "has_many :tags, :
|
31
|
+
# This is the "has_many :tags, through: :taggings" situation, where the join model
|
32
32
|
# typically has a belongs_to on both side. In other words, associations which could also
|
33
33
|
# be represented as has_and_belongs_to_many associations.
|
34
34
|
#
|