activerecord 5.0.0.beta2 → 5.0.0.beta3
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 +83 -20
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -0
- data/lib/active_record/associations/collection_association.rb +12 -1
- data/lib/active_record/associations/collection_proxy.rb +14 -0
- data/lib/active_record/associations/join_dependency/join_association.rb +13 -7
- data/lib/active_record/associations/preloader/association.rb +1 -1
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/attribute_assignment.rb +0 -8
- data/lib/active_record/attribute_methods.rb +0 -24
- data/lib/active_record/attribute_methods/read.rb +5 -17
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -2
- data/lib/active_record/attribute_methods/write.rb +0 -13
- data/lib/active_record/base.rb +0 -1
- data/lib/active_record/callbacks.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +4 -2
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +4 -6
- data/lib/active_record/connection_adapters/abstract_adapter.rb +1 -2
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +10 -16
- data/lib/active_record/connection_adapters/connection_specification.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +2 -2
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +3 -4
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +0 -1
- data/lib/active_record/core.rb +5 -0
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/inheritance.rb +1 -1
- data/lib/active_record/migration/compatibility.rb +1 -1
- data/lib/active_record/nested_attributes.rb +14 -6
- data/lib/active_record/null_relation.rb +1 -1
- data/lib/active_record/querying.rb +3 -3
- data/lib/active_record/reflection.rb +53 -36
- data/lib/active_record/relation.rb +26 -18
- data/lib/active_record/relation/batches.rb +4 -4
- data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
- data/lib/active_record/relation/calculations.rb +2 -10
- data/lib/active_record/relation/delegation.rb +2 -1
- data/lib/active_record/relation/finder_methods.rb +55 -26
- data/lib/active_record/relation/predicate_builder.rb +3 -4
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +10 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +11 -7
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/sanitization.rb +1 -1
- data/lib/active_record/schema_dumper.rb +6 -4
- data/lib/active_record/scoping/named.rb +10 -0
- data/lib/active_record/statement_cache.rb +1 -1
- data/lib/active_record/table_metadata.rb +5 -1
- data/lib/active_record/tasks/database_tasks.rb +4 -0
- data/lib/active_record/validations.rb +1 -1
- data/lib/active_record/validations/absence.rb +0 -1
- data/lib/active_record/validations/length.rb +0 -12
- data/lib/active_record/validations/presence.rb +0 -1
- data/lib/active_record/validations/uniqueness.rb +7 -9
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -0
- data/lib/rails/generators/active_record/model/templates/application_record.rb +3 -0
- metadata +9 -8
@@ -182,6 +182,7 @@ module ActiveRecord
|
|
182
182
|
end
|
183
183
|
CODE
|
184
184
|
end
|
185
|
+
alias_method :numeric, :decimal
|
185
186
|
end
|
186
187
|
|
187
188
|
# Represents the schema of an SQL table in an abstract way. This class
|
@@ -211,7 +212,7 @@ module ActiveRecord
|
|
211
212
|
def initialize(name, temporary, options, as = nil)
|
212
213
|
@columns_hash = {}
|
213
214
|
@indexes = {}
|
214
|
-
@foreign_keys =
|
215
|
+
@foreign_keys = []
|
215
216
|
@primary_keys = nil
|
216
217
|
@temporary = temporary
|
217
218
|
@options = options
|
@@ -329,7 +330,7 @@ module ActiveRecord
|
|
329
330
|
end
|
330
331
|
|
331
332
|
def foreign_key(table_name, options = {}) # :nodoc:
|
332
|
-
foreign_keys[table_name
|
333
|
+
foreign_keys.push([table_name, options])
|
333
334
|
end
|
334
335
|
|
335
336
|
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
|
@@ -436,6 +437,7 @@ module ActiveRecord
|
|
436
437
|
# t.bigint
|
437
438
|
# t.float
|
438
439
|
# t.decimal
|
440
|
+
# t.numeric
|
439
441
|
# t.datetime
|
440
442
|
# t.timestamp
|
441
443
|
# t.time
|
@@ -14,7 +14,7 @@ module ActiveRecord
|
|
14
14
|
|
15
15
|
def column_spec_for_primary_key(column)
|
16
16
|
return if column.type == :integer
|
17
|
-
spec = { id: column.
|
17
|
+
spec = { id: schema_type(column).inspect }
|
18
18
|
spec.merge!(prepare_column_options(column).delete_if { |key, _| [:name, :type].include?(key) })
|
19
19
|
end
|
20
20
|
|
@@ -24,7 +24,7 @@ module ActiveRecord
|
|
24
24
|
def prepare_column_options(column)
|
25
25
|
spec = {}
|
26
26
|
spec[:name] = column.name.inspect
|
27
|
-
spec[:type] = schema_type(column)
|
27
|
+
spec[:type] = schema_type(column).to_s
|
28
28
|
spec[:null] = 'false' unless column.null
|
29
29
|
|
30
30
|
if limit = schema_limit(column)
|
@@ -57,7 +57,7 @@ module ActiveRecord
|
|
57
57
|
private
|
58
58
|
|
59
59
|
def schema_type(column)
|
60
|
-
column.type
|
60
|
+
column.type
|
61
61
|
end
|
62
62
|
|
63
63
|
def schema_limit(column)
|
@@ -459,7 +459,7 @@ module ActiveRecord
|
|
459
459
|
# The +type+ parameter is normally one of the migrations native types,
|
460
460
|
# which is one of the following:
|
461
461
|
# <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>,
|
462
|
-
# <tt>:integer</tt>, <tt>:bigint</tt>, <tt>:float</tt>, <tt>:decimal</tt>,
|
462
|
+
# <tt>:integer</tt>, <tt>:bigint</tt>, <tt>:float</tt>, <tt>:decimal</tt>, <tt>:numeric</tt>,
|
463
463
|
# <tt>:datetime</tt>, <tt>:time</tt>, <tt>:date</tt>,
|
464
464
|
# <tt>:binary</tt>, <tt>:boolean</tt>.
|
465
465
|
#
|
@@ -477,9 +477,9 @@ module ActiveRecord
|
|
477
477
|
# Allows or disallows +NULL+ values in the column. This option could
|
478
478
|
# have been named <tt>:null_allowed</tt>.
|
479
479
|
# * <tt>:precision</tt> -
|
480
|
-
# Specifies the precision for
|
480
|
+
# Specifies the precision for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
|
481
481
|
# * <tt>:scale</tt> -
|
482
|
-
# Specifies the scale for
|
482
|
+
# Specifies the scale for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
|
483
483
|
#
|
484
484
|
# Note: The precision is the total number of significant digits
|
485
485
|
# and the scale is the number of digits that can be stored following
|
@@ -496,8 +496,6 @@ module ActiveRecord
|
|
496
496
|
# Default is (10,0).
|
497
497
|
# * PostgreSQL: <tt>:precision</tt> [1..infinity],
|
498
498
|
# <tt>:scale</tt> [0..infinity]. No default.
|
499
|
-
# * SQLite2: Any <tt>:precision</tt> and <tt>:scale</tt> may be used.
|
500
|
-
# Internal storage as strings. No default.
|
501
499
|
# * SQLite3: No restrictions on <tt>:precision</tt> and <tt>:scale</tt>,
|
502
500
|
# but the maximum supported <tt>:precision</tt> is 16. No default.
|
503
501
|
# * Oracle: <tt>:precision</tt> [1..38], <tt>:scale</tt> [-84..127].
|
@@ -700,7 +698,7 @@ module ActiveRecord
|
|
700
698
|
#
|
701
699
|
# CREATE FULLTEXT INDEX index_developers_on_name ON developers (name) -- MySQL
|
702
700
|
#
|
703
|
-
# Note: only supported by MySQL.
|
701
|
+
# Note: only supported by MySQL.
|
704
702
|
def add_index(table_name, column_name, options = {})
|
705
703
|
index_name, index_type, index_columns, index_options = add_index_options(table_name, column_name, options)
|
706
704
|
execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{index_columns})#{index_options}"
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'active_record/type'
|
2
|
-
require 'active_support/core_ext/benchmark'
|
3
2
|
require 'active_record/connection_adapters/determine_if_preparable_visitor'
|
4
3
|
require 'active_record/connection_adapters/schema_cache'
|
5
4
|
require 'active_record/connection_adapters/sql_type_metadata'
|
@@ -398,7 +397,7 @@ module ActiveRecord
|
|
398
397
|
if can_perform_case_insensitive_comparison_for?(column)
|
399
398
|
table[attribute].lower.eq(table.lower(Arel::Nodes::BindParam.new))
|
400
399
|
else
|
401
|
-
|
400
|
+
table[attribute].eq(Arel::Nodes::BindParam.new)
|
402
401
|
end
|
403
402
|
end
|
404
403
|
|
@@ -52,7 +52,6 @@ module ActiveRecord
|
|
52
52
|
INDEX_TYPES = [:fulltext, :spatial]
|
53
53
|
INDEX_USINGS = [:btree, :hash]
|
54
54
|
|
55
|
-
# FIXME: Make the first parameter more similar for the two adapters
|
56
55
|
def initialize(connection, logger, connection_options, config)
|
57
56
|
super(connection, logger, config)
|
58
57
|
@quoted_column_names, @quoted_table_names = {}, {}
|
@@ -65,6 +64,10 @@ module ActiveRecord
|
|
65
64
|
else
|
66
65
|
@prepared_statements = false
|
67
66
|
end
|
67
|
+
|
68
|
+
if version < '5.0.0'
|
69
|
+
raise "Your version of MySQL (#{full_version.match(/^\d+\.\d+\.\d+/)[0]}) is too old. Active Record supports MySQL >= 5.0."
|
70
|
+
end
|
68
71
|
end
|
69
72
|
|
70
73
|
CHARSETS_OF_4BYTES_MAXLEN = ['utf8mb4', 'utf16', 'utf16le', 'utf32']
|
@@ -98,12 +101,8 @@ module ActiveRecord
|
|
98
101
|
true
|
99
102
|
end
|
100
103
|
|
101
|
-
# MySQL 4 technically support transaction isolation, but it is affected by a bug
|
102
|
-
# where the transaction level gets persisted for the whole session:
|
103
|
-
#
|
104
|
-
# http://bugs.mysql.com/bug.php?id=39170
|
105
104
|
def supports_transaction_isolation?
|
106
|
-
|
105
|
+
true
|
107
106
|
end
|
108
107
|
|
109
108
|
def supports_explain?
|
@@ -119,17 +118,15 @@ module ActiveRecord
|
|
119
118
|
end
|
120
119
|
|
121
120
|
def supports_views?
|
122
|
-
|
121
|
+
true
|
123
122
|
end
|
124
123
|
|
125
124
|
def supports_datetime_with_precision?
|
126
125
|
version >= '5.6.4'
|
127
126
|
end
|
128
127
|
|
129
|
-
# 5.0.0 definitely supports it, possibly supported by earlier versions but
|
130
|
-
# not sure
|
131
128
|
def supports_advisory_locks?
|
132
|
-
|
129
|
+
true
|
133
130
|
end
|
134
131
|
|
135
132
|
def get_advisory_lock(lock_name, timeout = 0) # :nodoc:
|
@@ -618,13 +615,10 @@ module ActiveRecord
|
|
618
615
|
end
|
619
616
|
end
|
620
617
|
|
621
|
-
def
|
622
|
-
|
623
|
-
super
|
624
|
-
else
|
625
|
-
table[attribute].eq(Arel::Nodes::BindParam.new)
|
626
|
-
end
|
618
|
+
def can_perform_case_insensitive_comparison_for?(column)
|
619
|
+
column.case_sensitive?
|
627
620
|
end
|
621
|
+
private :can_perform_case_insensitive_comparison_for?
|
628
622
|
|
629
623
|
# In MySQL 5.7.5 and up, ONLY_FULL_GROUP_BY affects handling of queries that use
|
630
624
|
# DISTINCT and ORDER BY. It requires the ORDER BY columns in the select list for
|
@@ -33,7 +33,7 @@ module ActiveRecord
|
|
33
33
|
def initialize(url)
|
34
34
|
raise "Database URL cannot be empty" if url.blank?
|
35
35
|
@uri = uri_parser.parse(url)
|
36
|
-
@adapter = @uri.scheme.tr('-', '_')
|
36
|
+
@adapter = @uri.scheme && @uri.scheme.tr('-', '_')
|
37
37
|
@adapter = "postgresql" if @adapter == "postgres"
|
38
38
|
|
39
39
|
if @uri.opaque
|
@@ -12,7 +12,7 @@ module ActiveRecord
|
|
12
12
|
spec[:unsigned] = 'true' if column.unsigned?
|
13
13
|
return if spec.empty?
|
14
14
|
else
|
15
|
-
spec[:id] = column.
|
15
|
+
spec[:id] = schema_type(column).inspect
|
16
16
|
spec.merge!(prepare_column_options(column).delete_if { |key, _| [:name, :type, :null].include?(key) })
|
17
17
|
end
|
18
18
|
spec
|
@@ -32,7 +32,7 @@ module ActiveRecord
|
|
32
32
|
|
33
33
|
def schema_type(column)
|
34
34
|
if column.sql_type == 'tinyblob'
|
35
|
-
|
35
|
+
:blob
|
36
36
|
else
|
37
37
|
super
|
38
38
|
end
|
@@ -42,7 +42,7 @@ module ActiveRecord
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def supports_json?
|
45
|
-
version >= '5.7.8'
|
45
|
+
!mariadb? && version >= '5.7.8'
|
46
46
|
end
|
47
47
|
|
48
48
|
# HELPER METHODS ===========================================
|
@@ -134,8 +134,6 @@ module ActiveRecord
|
|
134
134
|
ActiveRecord::Result.new(result.fields, result.to_a)
|
135
135
|
end
|
136
136
|
|
137
|
-
alias exec_without_stmt exec_query
|
138
|
-
|
139
137
|
def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
|
140
138
|
execute to_sql(sql, binds), name
|
141
139
|
end
|
@@ -118,7 +118,7 @@ module ActiveRecord
|
|
118
118
|
alias :exec_update :exec_delete
|
119
119
|
|
120
120
|
def sql_for_insert(sql, pk, id_value, sequence_name, binds) # :nodoc:
|
121
|
-
|
121
|
+
if pk.nil?
|
122
122
|
# Extract the table from the insert sql. Yuck.
|
123
123
|
table_ref = extract_table_ref_from_insert_sql(sql)
|
124
124
|
pk = primary_key(table_ref) if table_ref
|
@@ -11,7 +11,7 @@ module ActiveRecord
|
|
11
11
|
spec[:id] = ':uuid'
|
12
12
|
spec[:default] = schema_default(column) || 'nil'
|
13
13
|
else
|
14
|
-
spec[:id] = column.
|
14
|
+
spec[:id] = schema_type(column).inspect
|
15
15
|
spec.merge!(prepare_column_options(column).delete_if { |key, _| [:name, :type, :null].include?(key) })
|
16
16
|
end
|
17
17
|
spec
|
@@ -35,9 +35,9 @@ module ActiveRecord
|
|
35
35
|
return super unless column.serial?
|
36
36
|
|
37
37
|
if column.bigint?
|
38
|
-
|
38
|
+
:bigserial
|
39
39
|
else
|
40
|
-
|
40
|
+
:serial
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -214,8 +214,8 @@ module ActiveRecord
|
|
214
214
|
@statements = StatementPool.new @connection,
|
215
215
|
self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 })
|
216
216
|
|
217
|
-
if postgresql_version <
|
218
|
-
raise "Your version of PostgreSQL (#{postgresql_version}) is too old
|
217
|
+
if postgresql_version < 90100
|
218
|
+
raise "Your version of PostgreSQL (#{postgresql_version}) is too old. Active Record supports PostgreSQL >= 9.1."
|
219
219
|
end
|
220
220
|
|
221
221
|
add_pg_decoders
|
@@ -297,9 +297,8 @@ module ActiveRecord
|
|
297
297
|
true
|
298
298
|
end
|
299
299
|
|
300
|
-
# Returns true if pg > 9.1
|
301
300
|
def supports_extensions?
|
302
|
-
|
301
|
+
true
|
303
302
|
end
|
304
303
|
|
305
304
|
# Range datatypes weren't introduced until PostgreSQL 9.2
|
data/lib/active_record/core.rb
CHANGED
@@ -256,6 +256,11 @@ module ActiveRecord
|
|
256
256
|
end
|
257
257
|
end
|
258
258
|
|
259
|
+
def arel_attribute(name, table = arel_table) # :nodoc:
|
260
|
+
name = attribute_alias(name) if attribute_alias?(name)
|
261
|
+
table[name]
|
262
|
+
end
|
263
|
+
|
259
264
|
def predicate_builder # :nodoc:
|
260
265
|
@predicate_builder ||= PredicateBuilder.new(table_metadata)
|
261
266
|
end
|
@@ -192,7 +192,7 @@ module ActiveRecord
|
|
192
192
|
end
|
193
193
|
|
194
194
|
def type_condition(table = arel_table)
|
195
|
-
sti_column = table
|
195
|
+
sti_column = arel_attribute(inheritance_column, table)
|
196
196
|
sti_names = ([self] + descendants).map(&:sti_name)
|
197
197
|
|
198
198
|
sti_column.in(sti_names)
|
@@ -102,7 +102,7 @@ module ActiveRecord
|
|
102
102
|
module Legacy
|
103
103
|
include FourTwoShared
|
104
104
|
|
105
|
-
def
|
105
|
+
def migrate(*)
|
106
106
|
ActiveSupport::Deprecation.warn \
|
107
107
|
"Directly inheriting from ActiveRecord::Migration is deprecated. " \
|
108
108
|
"Please specify the Rails release the migration was written for:\n" \
|
@@ -195,15 +195,23 @@ module ActiveRecord
|
|
195
195
|
# Nested attributes for an associated collection can also be passed in
|
196
196
|
# the form of a hash of hashes instead of an array of hashes:
|
197
197
|
#
|
198
|
-
# Member.create(
|
199
|
-
#
|
200
|
-
#
|
198
|
+
# Member.create(
|
199
|
+
# name: 'joe',
|
200
|
+
# posts_attributes: {
|
201
|
+
# first: { title: 'Foo' },
|
202
|
+
# second: { title: 'Bar' }
|
203
|
+
# }
|
204
|
+
# )
|
201
205
|
#
|
202
206
|
# has the same effect as
|
203
207
|
#
|
204
|
-
# Member.create(
|
205
|
-
#
|
206
|
-
#
|
208
|
+
# Member.create(
|
209
|
+
# name: 'joe',
|
210
|
+
# posts_attributes: [
|
211
|
+
# { title: 'Foo' },
|
212
|
+
# { title: 'Bar' }
|
213
|
+
# ]
|
214
|
+
# )
|
207
215
|
#
|
208
216
|
# The keys of the hash which is the value for +:posts_attributes+ are
|
209
217
|
# ignored in this case.
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module Querying
|
3
3
|
delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, to: :all
|
4
|
-
delegate :second, :second!, :third, :third!, :fourth, :fourth!, :fifth, :fifth!, :forty_two, :forty_two!, to: :all
|
4
|
+
delegate :second, :second!, :third, :third!, :fourth, :fourth!, :fifth, :fifth!, :forty_two, :forty_two!, :third_to_last, :third_to_last!, :second_to_last, :second_to_last!, to: :all
|
5
5
|
delegate :first_or_create, :first_or_create!, :first_or_initialize, to: :all
|
6
6
|
delegate :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, to: :all
|
7
7
|
delegate :find_by, :find_by!, to: :all
|
@@ -35,8 +35,8 @@ module ActiveRecord
|
|
35
35
|
#
|
36
36
|
# Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
|
37
37
|
# Post.find_by_sql ["SELECT body FROM comments WHERE author = :user_id OR approved_by = :user_id", { :user_id => user_id }]
|
38
|
-
def find_by_sql(sql, binds = [])
|
39
|
-
result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds)
|
38
|
+
def find_by_sql(sql, binds = [], preparable: nil)
|
39
|
+
result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds, preparable: preparable)
|
40
40
|
column_types = result_set.column_types.dup
|
41
41
|
columns_hash.each_key { |k| column_types.delete k }
|
42
42
|
message_bus = ActiveSupport::Notifications.instrumenter
|
@@ -124,8 +124,19 @@ module ActiveRecord
|
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
127
|
-
# Holds all the methods that are shared between MacroReflection
|
128
|
-
#
|
127
|
+
# Holds all the methods that are shared between MacroReflection and ThroughReflection.
|
128
|
+
#
|
129
|
+
# AbstractReflection
|
130
|
+
# MacroReflection
|
131
|
+
# AggregateReflection
|
132
|
+
# AssociationReflection
|
133
|
+
# HasManyReflection
|
134
|
+
# HasOneReflection
|
135
|
+
# BelongsToReflection
|
136
|
+
# HasAndBelongsToManyReflection
|
137
|
+
# ThroughReflection
|
138
|
+
# PolymorphicReflection
|
139
|
+
# RuntimeReflection
|
129
140
|
class AbstractReflection # :nodoc:
|
130
141
|
def table_name
|
131
142
|
klass.table_name
|
@@ -228,18 +239,14 @@ module ActiveRecord
|
|
228
239
|
def alias_candidate(name)
|
229
240
|
"#{plural_name}_#{name}"
|
230
241
|
end
|
242
|
+
|
243
|
+
def chain
|
244
|
+
collect_join_chain
|
245
|
+
end
|
231
246
|
end
|
232
247
|
|
233
248
|
# Base class for AggregateReflection and AssociationReflection. Objects of
|
234
249
|
# AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods.
|
235
|
-
#
|
236
|
-
# MacroReflection
|
237
|
-
# AggregateReflection
|
238
|
-
# AssociationReflection
|
239
|
-
# HasManyReflection
|
240
|
-
# HasOneReflection
|
241
|
-
# BelongsToReflection
|
242
|
-
# ThroughReflection
|
243
250
|
class MacroReflection < AbstractReflection
|
244
251
|
# Returns the name of the macro.
|
245
252
|
#
|
@@ -418,7 +425,7 @@ module ActiveRecord
|
|
418
425
|
|
419
426
|
# A chain of reflections from this one back to the owner. For more see the explanation in
|
420
427
|
# ThroughReflection.
|
421
|
-
def
|
428
|
+
def collect_join_chain
|
422
429
|
[self]
|
423
430
|
end
|
424
431
|
|
@@ -492,6 +499,18 @@ module ActiveRecord
|
|
492
499
|
VALID_AUTOMATIC_INVERSE_MACROS = [:has_many, :has_one, :belongs_to]
|
493
500
|
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:conditions, :through, :polymorphic, :foreign_key]
|
494
501
|
|
502
|
+
def add_as_source(seed)
|
503
|
+
seed
|
504
|
+
end
|
505
|
+
|
506
|
+
def add_as_polymorphic_through(reflection, seed)
|
507
|
+
seed + [PolymorphicReflection.new(self, reflection)]
|
508
|
+
end
|
509
|
+
|
510
|
+
def add_as_through(seed)
|
511
|
+
seed + [self]
|
512
|
+
end
|
513
|
+
|
495
514
|
protected
|
496
515
|
|
497
516
|
def actual_source_reflection # FIXME: this is a horrible name
|
@@ -594,10 +613,6 @@ module ActiveRecord
|
|
594
613
|
end
|
595
614
|
|
596
615
|
class HasManyReflection < AssociationReflection # :nodoc:
|
597
|
-
def initialize(name, scope, options, active_record)
|
598
|
-
super(name, scope, options, active_record)
|
599
|
-
end
|
600
|
-
|
601
616
|
def macro; :has_many; end
|
602
617
|
|
603
618
|
def collection?; true; end
|
@@ -612,10 +627,6 @@ module ActiveRecord
|
|
612
627
|
end
|
613
628
|
|
614
629
|
class HasOneReflection < AssociationReflection # :nodoc:
|
615
|
-
def initialize(name, scope, options, active_record)
|
616
|
-
super(name, scope, options, active_record)
|
617
|
-
end
|
618
|
-
|
619
630
|
def macro; :has_one; end
|
620
631
|
|
621
632
|
def has_one?; true; end
|
@@ -636,10 +647,6 @@ module ActiveRecord
|
|
636
647
|
end
|
637
648
|
|
638
649
|
class BelongsToReflection < AssociationReflection # :nodoc:
|
639
|
-
def initialize(name, scope, options, active_record)
|
640
|
-
super(name, scope, options, active_record)
|
641
|
-
end
|
642
|
-
|
643
650
|
def macro; :belongs_to; end
|
644
651
|
|
645
652
|
def belongs_to?; true; end
|
@@ -751,19 +758,8 @@ module ActiveRecord
|
|
751
758
|
# # => [<ActiveRecord::Reflection::ThroughReflection: @delegate_reflection=#<ActiveRecord::Reflection::HasManyReflection: @name=:tags...>,
|
752
759
|
# <ActiveRecord::Reflection::HasManyReflection: @name=:taggings, @options={}, @active_record=Post>]
|
753
760
|
#
|
754
|
-
def
|
755
|
-
|
756
|
-
a = source_reflection.chain
|
757
|
-
b = through_reflection.chain.map(&:dup)
|
758
|
-
|
759
|
-
if options[:source_type]
|
760
|
-
b[0] = PolymorphicReflection.new(b[0], self)
|
761
|
-
end
|
762
|
-
|
763
|
-
chain = a + b
|
764
|
-
chain[0] = self # Use self so we don't lose the information from :source_type
|
765
|
-
chain
|
766
|
-
end
|
761
|
+
def collect_join_chain
|
762
|
+
collect_join_reflections [self]
|
767
763
|
end
|
768
764
|
|
769
765
|
# This is for clearing cache on the reflection. Useful for tests that need to compare
|
@@ -922,6 +918,27 @@ module ActiveRecord
|
|
922
918
|
scope_chain
|
923
919
|
end
|
924
920
|
|
921
|
+
def add_as_source(seed)
|
922
|
+
collect_join_reflections seed
|
923
|
+
end
|
924
|
+
|
925
|
+
def add_as_polymorphic_through(reflection, seed)
|
926
|
+
collect_join_reflections(seed + [PolymorphicReflection.new(self, reflection)])
|
927
|
+
end
|
928
|
+
|
929
|
+
def add_as_through(seed)
|
930
|
+
collect_join_reflections(seed + [self])
|
931
|
+
end
|
932
|
+
|
933
|
+
def collect_join_reflections(seed)
|
934
|
+
a = source_reflection.add_as_source seed
|
935
|
+
if options[:source_type]
|
936
|
+
through_reflection.add_as_polymorphic_through self, a
|
937
|
+
else
|
938
|
+
through_reflection.add_as_through a
|
939
|
+
end
|
940
|
+
end
|
941
|
+
|
925
942
|
protected
|
926
943
|
|
927
944
|
def actual_source_reflection # FIXME: this is a horrible name
|