activerecord 5.0.7.2 → 5.1.0.beta1

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.

Files changed (216) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +389 -2252
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/examples/performance.rb +28 -28
  6. data/examples/simple.rb +3 -3
  7. data/lib/active_record.rb +20 -20
  8. data/lib/active_record/aggregations.rb +244 -244
  9. data/lib/active_record/association_relation.rb +5 -5
  10. data/lib/active_record/associations.rb +1579 -1569
  11. data/lib/active_record/associations/alias_tracker.rb +1 -1
  12. data/lib/active_record/associations/association.rb +23 -15
  13. data/lib/active_record/associations/association_scope.rb +83 -81
  14. data/lib/active_record/associations/belongs_to_association.rb +0 -1
  15. data/lib/active_record/associations/builder/belongs_to.rb +16 -14
  16. data/lib/active_record/associations/builder/collection_association.rb +1 -2
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
  18. data/lib/active_record/associations/collection_association.rb +74 -241
  19. data/lib/active_record/associations/collection_proxy.rb +144 -70
  20. data/lib/active_record/associations/has_many_association.rb +15 -19
  21. data/lib/active_record/associations/has_many_through_association.rb +12 -5
  22. data/lib/active_record/associations/has_one_association.rb +22 -28
  23. data/lib/active_record/associations/has_one_through_association.rb +5 -1
  24. data/lib/active_record/associations/join_dependency.rb +117 -115
  25. data/lib/active_record/associations/join_dependency/join_association.rb +16 -13
  26. data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
  27. data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
  28. data/lib/active_record/associations/preloader.rb +94 -94
  29. data/lib/active_record/associations/preloader/association.rb +87 -64
  30. data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
  31. data/lib/active_record/associations/preloader/collection_association.rb +6 -6
  32. data/lib/active_record/associations/preloader/has_many.rb +0 -2
  33. data/lib/active_record/associations/preloader/singular_association.rb +6 -8
  34. data/lib/active_record/associations/preloader/through_association.rb +34 -41
  35. data/lib/active_record/associations/singular_association.rb +8 -25
  36. data/lib/active_record/associations/through_association.rb +3 -6
  37. data/lib/active_record/attribute.rb +98 -71
  38. data/lib/active_record/attribute/user_provided_default.rb +4 -2
  39. data/lib/active_record/attribute_assignment.rb +61 -61
  40. data/lib/active_record/attribute_decorators.rb +35 -13
  41. data/lib/active_record/attribute_methods.rb +56 -65
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
  43. data/lib/active_record/attribute_methods/dirty.rb +216 -34
  44. data/lib/active_record/attribute_methods/primary_key.rb +78 -73
  45. data/lib/active_record/attribute_methods/read.rb +39 -35
  46. data/lib/active_record/attribute_methods/serialization.rb +7 -7
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
  48. data/lib/active_record/attribute_methods/write.rb +36 -30
  49. data/lib/active_record/attribute_mutation_tracker.rb +53 -10
  50. data/lib/active_record/attribute_set.rb +9 -6
  51. data/lib/active_record/attribute_set/builder.rb +41 -49
  52. data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
  53. data/lib/active_record/attributes.rb +21 -21
  54. data/lib/active_record/autosave_association.rb +13 -13
  55. data/lib/active_record/base.rb +24 -22
  56. data/lib/active_record/callbacks.rb +52 -14
  57. data/lib/active_record/coders/yaml_column.rb +9 -11
  58. data/lib/active_record/collection_cache_key.rb +6 -17
  59. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +320 -278
  60. data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
  61. data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -34
  62. data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -27
  63. data/lib/active_record/connection_adapters/abstract/quoting.rb +44 -57
  64. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +9 -19
  65. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +78 -79
  66. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
  67. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +99 -93
  68. data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -5
  69. data/lib/active_record/connection_adapters/abstract_adapter.rb +156 -128
  70. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +424 -382
  71. data/lib/active_record/connection_adapters/column.rb +27 -5
  72. data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
  73. data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
  74. data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -43
  75. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
  76. data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
  77. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
  78. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
  79. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +49 -31
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +5 -6
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +24 -26
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +1 -28
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -35
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +9 -9
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
  91. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
  92. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
  93. data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
  94. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  95. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
  97. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +28 -30
  98. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
  100. data/lib/active_record/connection_adapters/postgresql/quoting.rb +38 -36
  101. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
  102. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
  103. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
  104. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +161 -170
  105. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +4 -4
  106. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -7
  107. data/lib/active_record/connection_adapters/postgresql_adapter.rb +179 -152
  108. data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
  109. data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
  110. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
  111. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -20
  112. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
  113. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
  114. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
  115. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +187 -130
  116. data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
  117. data/lib/active_record/connection_handling.rb +14 -26
  118. data/lib/active_record/core.rb +110 -93
  119. data/lib/active_record/counter_cache.rb +62 -13
  120. data/lib/active_record/define_callbacks.rb +20 -0
  121. data/lib/active_record/dynamic_matchers.rb +80 -79
  122. data/lib/active_record/enum.rb +8 -6
  123. data/lib/active_record/errors.rb +58 -15
  124. data/lib/active_record/explain.rb +1 -2
  125. data/lib/active_record/explain_registry.rb +1 -1
  126. data/lib/active_record/explain_subscriber.rb +7 -4
  127. data/lib/active_record/fixture_set/file.rb +11 -8
  128. data/lib/active_record/fixtures.rb +66 -53
  129. data/lib/active_record/gem_version.rb +3 -3
  130. data/lib/active_record/inheritance.rb +93 -79
  131. data/lib/active_record/integration.rb +7 -7
  132. data/lib/active_record/internal_metadata.rb +3 -16
  133. data/lib/active_record/legacy_yaml_adapter.rb +1 -1
  134. data/lib/active_record/locking/optimistic.rb +64 -56
  135. data/lib/active_record/locking/pessimistic.rb +10 -1
  136. data/lib/active_record/log_subscriber.rb +29 -29
  137. data/lib/active_record/migration.rb +155 -172
  138. data/lib/active_record/migration/command_recorder.rb +94 -94
  139. data/lib/active_record/migration/compatibility.rb +76 -37
  140. data/lib/active_record/migration/join_table.rb +6 -6
  141. data/lib/active_record/model_schema.rb +85 -119
  142. data/lib/active_record/nested_attributes.rb +200 -199
  143. data/lib/active_record/null_relation.rb +10 -33
  144. data/lib/active_record/persistence.rb +45 -38
  145. data/lib/active_record/query_cache.rb +4 -8
  146. data/lib/active_record/querying.rb +2 -3
  147. data/lib/active_record/railtie.rb +16 -17
  148. data/lib/active_record/railties/controller_runtime.rb +6 -2
  149. data/lib/active_record/railties/databases.rake +125 -140
  150. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  151. data/lib/active_record/readonly_attributes.rb +2 -2
  152. data/lib/active_record/reflection.rb +79 -96
  153. data/lib/active_record/relation.rb +72 -115
  154. data/lib/active_record/relation/batches.rb +87 -58
  155. data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
  156. data/lib/active_record/relation/calculations.rb +154 -160
  157. data/lib/active_record/relation/delegation.rb +30 -29
  158. data/lib/active_record/relation/finder_methods.rb +195 -226
  159. data/lib/active_record/relation/merger.rb +58 -62
  160. data/lib/active_record/relation/predicate_builder.rb +92 -89
  161. data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
  162. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
  163. data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
  164. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
  165. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
  166. data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
  167. data/lib/active_record/relation/query_attribute.rb +1 -1
  168. data/lib/active_record/relation/query_methods.rb +247 -295
  169. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  170. data/lib/active_record/relation/spawn_methods.rb +4 -5
  171. data/lib/active_record/relation/where_clause.rb +79 -65
  172. data/lib/active_record/relation/where_clause_factory.rb +47 -8
  173. data/lib/active_record/result.rb +29 -31
  174. data/lib/active_record/runtime_registry.rb +3 -3
  175. data/lib/active_record/sanitization.rb +182 -197
  176. data/lib/active_record/schema.rb +3 -3
  177. data/lib/active_record/schema_dumper.rb +14 -37
  178. data/lib/active_record/schema_migration.rb +3 -3
  179. data/lib/active_record/scoping.rb +9 -10
  180. data/lib/active_record/scoping/default.rb +87 -91
  181. data/lib/active_record/scoping/named.rb +16 -28
  182. data/lib/active_record/secure_token.rb +2 -2
  183. data/lib/active_record/statement_cache.rb +13 -15
  184. data/lib/active_record/store.rb +31 -32
  185. data/lib/active_record/suppressor.rb +2 -1
  186. data/lib/active_record/table_metadata.rb +9 -5
  187. data/lib/active_record/tasks/database_tasks.rb +72 -65
  188. data/lib/active_record/tasks/mysql_database_tasks.rb +75 -72
  189. data/lib/active_record/tasks/postgresql_database_tasks.rb +53 -48
  190. data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
  191. data/lib/active_record/timestamp.rb +39 -25
  192. data/lib/active_record/touch_later.rb +1 -2
  193. data/lib/active_record/transactions.rb +98 -110
  194. data/lib/active_record/type.rb +17 -13
  195. data/lib/active_record/type/adapter_specific_registry.rb +46 -42
  196. data/lib/active_record/type/decimal_without_scale.rb +9 -0
  197. data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
  198. data/lib/active_record/type/serialized.rb +8 -8
  199. data/lib/active_record/type/text.rb +9 -0
  200. data/lib/active_record/type/time.rb +0 -1
  201. data/lib/active_record/type/type_map.rb +11 -15
  202. data/lib/active_record/type/unsigned_integer.rb +15 -0
  203. data/lib/active_record/type_caster.rb +2 -2
  204. data/lib/active_record/type_caster/connection.rb +8 -6
  205. data/lib/active_record/type_caster/map.rb +3 -1
  206. data/lib/active_record/validations.rb +4 -4
  207. data/lib/active_record/validations/associated.rb +1 -1
  208. data/lib/active_record/validations/presence.rb +2 -2
  209. data/lib/active_record/validations/uniqueness.rb +8 -39
  210. data/lib/active_record/version.rb +1 -1
  211. data/lib/rails/generators/active_record.rb +4 -4
  212. data/lib/rails/generators/active_record/migration.rb +2 -2
  213. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
  214. data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
  215. metadata +22 -13
  216. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -31,9 +31,6 @@ module ActiveRecord
31
31
  def initialize(klass, association) #:nodoc:
32
32
  @association = association
33
33
  super klass, klass.arel_table, klass.predicate_builder
34
-
35
- extensions = association.extensions
36
- extend(*extensions) if extensions.any?
37
34
  end
38
35
 
39
36
  def target
@@ -53,6 +50,12 @@ module ActiveRecord
53
50
  @association.loaded?
54
51
  end
55
52
 
53
+ ##
54
+ # :method: select
55
+ #
56
+ # :call-seq:
57
+ # select(*fields, &block)
58
+ #
56
59
  # Works in two ways.
57
60
  #
58
61
  # *First:* Specify a subset of fields to be selected from the result set.
@@ -100,15 +103,6 @@ module ActiveRecord
100
103
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
101
104
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
102
105
  # # ]
103
- #
104
- # person.pets.select(:name) { |pet| pet.name =~ /oo/ }
105
- # # => [
106
- # # #<Pet id: 2, name: "Spook">,
107
- # # #<Pet id: 3, name: "Choo-Choo">
108
- # # ]
109
- def select(*fields, &block)
110
- @association.select(*fields, &block)
111
- end
112
106
 
113
107
  # Finds an object in the collection responding to the +id+. Uses the same
114
108
  # rules as ActiveRecord::Base.find. Returns ActiveRecord::RecordNotFound
@@ -140,6 +134,12 @@ module ActiveRecord
140
134
  @association.find(*args, &block)
141
135
  end
142
136
 
137
+ ##
138
+ # :method: first
139
+ #
140
+ # :call-seq:
141
+ # first(limit = nil)
142
+ #
143
143
  # Returns the first record, or the first +n+ records, from the collection.
144
144
  # If the collection is empty, the first form returns +nil+, and the second
145
145
  # form returns an empty array.
@@ -166,45 +166,63 @@ module ActiveRecord
166
166
  # another_person_without.pets # => []
167
167
  # another_person_without.pets.first # => nil
168
168
  # another_person_without.pets.first(3) # => []
169
- def first(*args)
170
- @association.first(*args)
171
- end
172
169
 
170
+ ##
171
+ # :method: second
172
+ #
173
+ # :call-seq:
174
+ # second()
175
+ #
173
176
  # Same as #first except returns only the second record.
174
- def second(*args)
175
- @association.second(*args)
176
- end
177
177
 
178
+ ##
179
+ # :method: third
180
+ #
181
+ # :call-seq:
182
+ # third()
183
+ #
178
184
  # Same as #first except returns only the third record.
179
- def third(*args)
180
- @association.third(*args)
181
- end
182
185
 
186
+ ##
187
+ # :method: fourth
188
+ #
189
+ # :call-seq:
190
+ # fourth()
191
+ #
183
192
  # Same as #first except returns only the fourth record.
184
- def fourth(*args)
185
- @association.fourth(*args)
186
- end
187
193
 
194
+ ##
195
+ # :method: fifth
196
+ #
197
+ # :call-seq:
198
+ # fifth()
199
+ #
188
200
  # Same as #first except returns only the fifth record.
189
- def fifth(*args)
190
- @association.fifth(*args)
191
- end
192
201
 
202
+ ##
203
+ # :method: forty_two
204
+ #
205
+ # :call-seq:
206
+ # forty_two()
207
+ #
193
208
  # Same as #first except returns only the forty second record.
194
209
  # Also known as accessing "the reddit".
195
- def forty_two(*args)
196
- @association.forty_two(*args)
197
- end
198
210
 
211
+ ##
212
+ # :method: third_to_last
213
+ #
214
+ # :call-seq:
215
+ # third_to_last()
216
+ #
199
217
  # Same as #first except returns only the third-to-last record.
200
- def third_to_last(*args)
201
- @association.third_to_last(*args)
202
- end
203
218
 
219
+ ##
220
+ # :method: second_to_last
221
+ #
222
+ # :call-seq:
223
+ # second_to_last()
224
+ #
204
225
  # Same as #first except returns only the second-to-last record.
205
- def second_to_last(*args)
206
- @association.second_to_last(*args)
207
- end
208
226
 
209
227
  # Returns the last record, or the last +n+ records, from the collection.
210
228
  # If the collection is empty, the first form returns +nil+, and the second
@@ -232,8 +250,9 @@ module ActiveRecord
232
250
  # another_person_without.pets # => []
233
251
  # another_person_without.pets.last # => nil
234
252
  # another_person_without.pets.last(3) # => []
235
- def last(*args)
236
- @association.last(*args)
253
+ def last(limit = nil)
254
+ load_target if find_from_target?
255
+ super
237
256
  end
238
257
 
239
258
  # Gives a record (or N records if a parameter is supplied) from the collection
@@ -261,8 +280,9 @@ module ActiveRecord
261
280
  # another_person_without.pets # => []
262
281
  # another_person_without.pets.take # => nil
263
282
  # another_person_without.pets.take(2) # => []
264
- def take(n = nil)
265
- @association.take(n)
283
+ def take(limit = nil)
284
+ load_target if find_from_target?
285
+ super
266
286
  end
267
287
 
268
288
  # Returns a new object of the collection type that has been instantiated
@@ -695,6 +715,12 @@ module ActiveRecord
695
715
  @association.destroy(*records)
696
716
  end
697
717
 
718
+ ##
719
+ # :method: distinct
720
+ #
721
+ # :call-seq:
722
+ # distinct(value = true)
723
+ #
698
724
  # Specifies whether the records should be unique or not.
699
725
  #
700
726
  # class Person < ActiveRecord::Base
@@ -709,17 +735,39 @@ module ActiveRecord
709
735
  #
710
736
  # person.pets.select(:name).distinct
711
737
  # # => [#<Pet name: "Fancy-Fancy">]
712
- def distinct
713
- @association.distinct
738
+ #
739
+ # person.pets.select(:name).distinct.distinct(false)
740
+ # # => [
741
+ # # #<Pet name: "Fancy-Fancy">,
742
+ # # #<Pet name: "Fancy-Fancy">
743
+ # # ]
744
+
745
+ #--
746
+ def uniq
747
+ load_target.uniq
714
748
  end
715
- alias uniq distinct
716
749
 
717
- # Count all records using SQL.
750
+ def calculate(operation, column_name)
751
+ null_scope? ? scope.calculate(operation, column_name) : super
752
+ end
753
+
754
+ def pluck(*column_names)
755
+ null_scope? ? scope.pluck(*column_names) : super
756
+ end
757
+
758
+ ##
759
+ # :method: count
760
+ #
761
+ # :call-seq:
762
+ # count(column_name = nil, &block)
763
+ #
764
+ # Count all records.
718
765
  #
719
766
  # class Person < ActiveRecord::Base
720
767
  # has_many :pets
721
768
  # end
722
769
  #
770
+ # # This will perform the count using SQL.
723
771
  # person.pets.count # => 3
724
772
  # person.pets
725
773
  # # => [
@@ -727,17 +775,11 @@ module ActiveRecord
727
775
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
728
776
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
729
777
  # # ]
730
- def count(column_name = nil)
731
- @association.count(column_name)
732
- end
733
-
734
- def calculate(operation, column_name)
735
- null_scope? ? scope.calculate(operation, column_name) : super
736
- end
737
-
738
- def pluck(*column_names)
739
- null_scope? ? scope.pluck(*column_names) : super
740
- end
778
+ #
779
+ # Passing a block will select all of a person's pets in SQL and then
780
+ # perform the count using Ruby.
781
+ #
782
+ # person.pets.count { |pet| pet.name.include?('-') } # => 2
741
783
 
742
784
  # Returns the size of the collection. If the collection hasn't been loaded,
743
785
  # it executes a <tt>SELECT COUNT(*)</tt> query. Else it calls <tt>collection.size</tt>.
@@ -767,6 +809,12 @@ module ActiveRecord
767
809
  @association.size
768
810
  end
769
811
 
812
+ ##
813
+ # :method: length
814
+ #
815
+ # :call-seq:
816
+ # length()
817
+ #
770
818
  # Returns the size of the collection calling +size+ on the target.
771
819
  # If the collection has been already loaded, +length+ and +size+ are
772
820
  # equivalent. If not and you are going to need the records anyway this
@@ -787,9 +835,6 @@ module ActiveRecord
787
835
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
788
836
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
789
837
  # # ]
790
- def length
791
- @association.length
792
- end
793
838
 
794
839
  # Returns +true+ if the collection is empty. If the collection has been
795
840
  # loaded it is equivalent
@@ -813,6 +858,12 @@ module ActiveRecord
813
858
  @association.empty?
814
859
  end
815
860
 
861
+ ##
862
+ # :method: any?
863
+ #
864
+ # :call-seq:
865
+ # any?()
866
+ #
816
867
  # Returns +true+ if the collection is not empty.
817
868
  #
818
869
  # class Person < ActiveRecord::Base
@@ -842,10 +893,13 @@ module ActiveRecord
842
893
  # pet.group == 'dogs'
843
894
  # end
844
895
  # # => true
845
- def any?(&block)
846
- @association.any?(&block)
847
- end
848
896
 
897
+ ##
898
+ # :method: many?
899
+ #
900
+ # :call-seq:
901
+ # many?()
902
+ #
849
903
  # Returns true if the collection has more than one record.
850
904
  # Equivalent to <tt>collection.size > 1</tt>.
851
905
  #
@@ -880,9 +934,6 @@ module ActiveRecord
880
934
  # pet.group == 'cats'
881
935
  # end
882
936
  # # => true
883
- def many?(&block)
884
- @association.many?(&block)
885
- end
886
937
 
887
938
  # Returns +true+ if the given +record+ is present in the collection.
888
939
  #
@@ -1037,8 +1088,9 @@ module ActiveRecord
1037
1088
  # person.pets(true) # fetches pets from the database
1038
1089
  # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
1039
1090
  def reload
1091
+ @scope = nil
1040
1092
  proxy_association.reload
1041
- reset_scope
1093
+ self
1042
1094
  end
1043
1095
 
1044
1096
  # Unloads the association. Returns +self+.
@@ -1058,13 +1110,9 @@ module ActiveRecord
1058
1110
  # person.pets # fetches pets from the database
1059
1111
  # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
1060
1112
  def reset
1113
+ @scope = nil
1061
1114
  proxy_association.reset
1062
1115
  proxy_association.reset_scope
1063
- reset_scope
1064
- end
1065
-
1066
- def reset_scope # :nodoc:
1067
- @scope = nil
1068
1116
  self
1069
1117
  end
1070
1118
 
@@ -1079,13 +1127,39 @@ module ActiveRecord
1079
1127
 
1080
1128
  private
1081
1129
 
1130
+ def find_nth_with_limit(index, limit)
1131
+ load_target if find_from_target?
1132
+ super
1133
+ end
1134
+
1135
+ def find_nth_from_last(index)
1136
+ load_target if find_from_target?
1137
+ super
1138
+ end
1139
+
1082
1140
  def null_scope?
1083
1141
  @association.null_scope?
1084
1142
  end
1085
1143
 
1144
+ def find_from_target?
1145
+ @association.find_from_target?
1146
+ end
1147
+
1086
1148
  def exec_queries
1087
1149
  load_target
1088
1150
  end
1151
+
1152
+ def respond_to_missing?(method, _)
1153
+ scope.respond_to?(method) || super
1154
+ end
1155
+
1156
+ def method_missing(method, *args, &block)
1157
+ if scope.respond_to?(method)
1158
+ scope.public_send(method, *args, &block)
1159
+ else
1160
+ super
1161
+ end
1162
+ end
1089
1163
  end
1090
1164
  end
1091
1165
  end
@@ -16,31 +16,27 @@ module ActiveRecord
16
16
  when :restrict_with_error
17
17
  unless empty?
18
18
  record = owner.class.human_attribute_name(reflection.name).downcase
19
- message = owner.errors.generate_message(:base, :'restrict_dependent_destroy.many', record: record, raise: true) rescue nil
20
- if message
21
- ActiveSupport::Deprecation.warn(<<-MESSAGE.squish)
22
- The error key `:'restrict_dependent_destroy.many'` has been deprecated and will be removed in Rails 5.1.
23
- Please use `:'restrict_dependent_destroy.has_many'` instead.
24
- MESSAGE
25
- end
26
- owner.errors.add(:base, message || :'restrict_dependent_destroy.has_many', record: record)
19
+ owner.errors.add(:base, :'restrict_dependent_destroy.has_many', record: record)
27
20
  throw(:abort)
28
21
  end
29
22
 
23
+ when :destroy
24
+ # No point in executing the counter update since we're going to destroy the parent anyway
25
+ load_target.each { |t| t.destroyed_by_association = reflection }
26
+ destroy_all
30
27
  else
31
- if options[:dependent] == :destroy
32
- # No point in executing the counter update since we're going to destroy the parent anyway
33
- load_target.each { |t| t.destroyed_by_association = reflection }
34
- destroy_all
35
- else
36
- delete_all
37
- end
28
+ delete_all
38
29
  end
39
30
  end
40
31
 
41
32
  def insert_record(record, validate = true, raise = false)
42
33
  set_owner_attributes(record)
43
- super
34
+
35
+ if raise
36
+ record.save!(validate: validate)
37
+ else
38
+ record.save(validate: validate)
39
+ end
44
40
  end
45
41
 
46
42
  def empty?
@@ -68,7 +64,7 @@ module ActiveRecord
68
64
  # the loaded flag is set to true as well.
69
65
  def count_records
70
66
  count = if reflection.has_cached_counter?
71
- owner._read_attribute reflection.counter_cache_column
67
+ owner._read_attribute(reflection.counter_cache_column).to_i
72
68
  else
73
69
  scope.count
74
70
  end
@@ -76,7 +72,7 @@ module ActiveRecord
76
72
  # If there's nothing in the database and @target has no new records
77
73
  # we are certain the current target is an empty array. This is a
78
74
  # documented side-effect of the method that may avoid an extra SELECT.
79
- @target ||= [] and loaded! if count == 0
75
+ (@target ||= []) && loaded! if count == 0
80
76
 
81
77
  [association_scope.limit_value, count].compact.min
82
78
  end
@@ -104,7 +100,7 @@ module ActiveRecord
104
100
  end
105
101
 
106
102
  def delete_or_nullify_all_records(method)
107
- count = delete_count(method, self.scope)
103
+ count = delete_count(method, scope)
108
104
  update_counter(-count)
109
105
  end
110
106
 
@@ -38,8 +38,12 @@ module ActiveRecord
38
38
  def insert_record(record, validate = true, raise = false)
39
39
  ensure_not_nested
40
40
 
41
- if record.new_record? || record.changed?
42
- return unless super
41
+ if record.new_record? || record.has_changes_to_save?
42
+ if raise
43
+ record.save!(validate: validate)
44
+ else
45
+ return unless record.save(validate: validate)
46
+ end
43
47
  end
44
48
 
45
49
  save_through_record(record)
@@ -84,7 +88,10 @@ module ActiveRecord
84
88
  end
85
89
 
86
90
  def save_through_record(record)
87
- build_through_record(record).save!
91
+ association = build_through_record(record)
92
+ if association.changed?
93
+ association.save!
94
+ end
88
95
  ensure
89
96
  @through_records.delete(record.object_id)
90
97
  end
@@ -144,7 +151,7 @@ module ActiveRecord
144
151
  stmt.from scope.klass.arel_table
145
152
  stmt.wheres = arel.constraints
146
153
 
147
- count = scope.klass.connection.delete(stmt, 'SQL', scope.bound_attributes)
154
+ count = scope.klass.connection.delete(stmt, "SQL", scope.bound_attributes)
148
155
  end
149
156
  when :nullify
150
157
  count = scope.update_all(source_reflection.foreign_key => nil)
@@ -194,7 +201,7 @@ module ActiveRecord
194
201
 
195
202
  def find_target
196
203
  return [] unless target_reflection_has_associated_record?
197
- get_records
204
+ super
198
205
  end
199
206
 
200
207
  # NOTE - not sure that we can actually cope with inverses here