activerecord 4.2.11.1 → 5.0.0

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 (246) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1282 -1195
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +7 -8
  5. data/examples/performance.rb +2 -3
  6. data/examples/simple.rb +0 -1
  7. data/lib/active_record.rb +8 -4
  8. data/lib/active_record/aggregations.rb +35 -24
  9. data/lib/active_record/association_relation.rb +3 -3
  10. data/lib/active_record/associations.rb +317 -209
  11. data/lib/active_record/associations/alias_tracker.rb +19 -16
  12. data/lib/active_record/associations/association.rb +11 -9
  13. data/lib/active_record/associations/association_scope.rb +73 -102
  14. data/lib/active_record/associations/belongs_to_association.rb +21 -32
  15. data/lib/active_record/associations/builder/association.rb +28 -34
  16. data/lib/active_record/associations/builder/belongs_to.rb +43 -18
  17. data/lib/active_record/associations/builder/collection_association.rb +7 -19
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +14 -11
  19. data/lib/active_record/associations/builder/has_many.rb +4 -4
  20. data/lib/active_record/associations/builder/has_one.rb +11 -6
  21. data/lib/active_record/associations/builder/singular_association.rb +3 -10
  22. data/lib/active_record/associations/collection_association.rb +49 -41
  23. data/lib/active_record/associations/collection_proxy.rb +67 -27
  24. data/lib/active_record/associations/foreign_association.rb +1 -1
  25. data/lib/active_record/associations/has_many_association.rb +20 -71
  26. data/lib/active_record/associations/has_many_through_association.rb +8 -47
  27. data/lib/active_record/associations/has_one_association.rb +12 -5
  28. data/lib/active_record/associations/join_dependency.rb +29 -19
  29. data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
  30. data/lib/active_record/associations/preloader.rb +14 -4
  31. data/lib/active_record/associations/preloader/association.rb +46 -52
  32. data/lib/active_record/associations/preloader/collection_association.rb +0 -6
  33. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  34. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  35. data/lib/active_record/associations/preloader/through_association.rb +27 -14
  36. data/lib/active_record/associations/singular_association.rb +7 -1
  37. data/lib/active_record/associations/through_association.rb +11 -3
  38. data/lib/active_record/attribute.rb +68 -18
  39. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  40. data/lib/active_record/attribute_assignment.rb +19 -140
  41. data/lib/active_record/attribute_decorators.rb +6 -5
  42. data/lib/active_record/attribute_methods.rb +76 -47
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  44. data/lib/active_record/attribute_methods/dirty.rb +46 -86
  45. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  46. data/lib/active_record/attribute_methods/query.rb +2 -2
  47. data/lib/active_record/attribute_methods/read.rb +31 -59
  48. data/lib/active_record/attribute_methods/serialization.rb +13 -16
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
  50. data/lib/active_record/attribute_methods/write.rb +13 -37
  51. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  52. data/lib/active_record/attribute_set.rb +30 -3
  53. data/lib/active_record/attribute_set/builder.rb +6 -4
  54. data/lib/active_record/attributes.rb +199 -81
  55. data/lib/active_record/autosave_association.rb +49 -16
  56. data/lib/active_record/base.rb +32 -23
  57. data/lib/active_record/callbacks.rb +39 -43
  58. data/lib/active_record/coders/json.rb +1 -1
  59. data/lib/active_record/coders/yaml_column.rb +20 -8
  60. data/lib/active_record/collection_cache_key.rb +40 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
  62. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  63. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
  64. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
  65. data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -10
  66. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  67. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
  68. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -185
  69. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
  70. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +380 -141
  71. data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
  72. data/lib/active_record/connection_adapters/abstract_adapter.rb +141 -59
  73. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -370
  74. data/lib/active_record/connection_adapters/column.rb +28 -43
  75. data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
  76. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  77. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  78. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  79. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  80. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  81. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  82. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  83. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  84. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  85. data/lib/active_record/connection_adapters/mysql2_adapter.rb +29 -166
  86. data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
  87. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
  88. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -57
  91. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  94. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
  96. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  100. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  106. data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
  107. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  108. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  109. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
  111. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  112. data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
  113. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  114. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  115. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  116. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  117. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  118. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +149 -192
  119. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  120. data/lib/active_record/connection_handling.rb +37 -14
  121. data/lib/active_record/core.rb +89 -107
  122. data/lib/active_record/counter_cache.rb +13 -24
  123. data/lib/active_record/dynamic_matchers.rb +1 -20
  124. data/lib/active_record/enum.rb +113 -76
  125. data/lib/active_record/errors.rb +87 -48
  126. data/lib/active_record/explain_registry.rb +1 -1
  127. data/lib/active_record/explain_subscriber.rb +1 -1
  128. data/lib/active_record/fixture_set/file.rb +26 -5
  129. data/lib/active_record/fixtures.rb +76 -40
  130. data/lib/active_record/gem_version.rb +4 -4
  131. data/lib/active_record/inheritance.rb +32 -40
  132. data/lib/active_record/integration.rb +4 -4
  133. data/lib/active_record/internal_metadata.rb +56 -0
  134. data/lib/active_record/legacy_yaml_adapter.rb +18 -2
  135. data/lib/active_record/locale/en.yml +3 -2
  136. data/lib/active_record/locking/optimistic.rb +15 -15
  137. data/lib/active_record/locking/pessimistic.rb +1 -1
  138. data/lib/active_record/log_subscriber.rb +43 -21
  139. data/lib/active_record/migration.rb +363 -133
  140. data/lib/active_record/migration/command_recorder.rb +59 -18
  141. data/lib/active_record/migration/compatibility.rb +126 -0
  142. data/lib/active_record/model_schema.rb +129 -41
  143. data/lib/active_record/nested_attributes.rb +58 -29
  144. data/lib/active_record/null_relation.rb +16 -8
  145. data/lib/active_record/persistence.rb +121 -80
  146. data/lib/active_record/query_cache.rb +15 -18
  147. data/lib/active_record/querying.rb +10 -9
  148. data/lib/active_record/railtie.rb +23 -16
  149. data/lib/active_record/railties/controller_runtime.rb +1 -1
  150. data/lib/active_record/railties/databases.rake +69 -46
  151. data/lib/active_record/readonly_attributes.rb +1 -1
  152. data/lib/active_record/reflection.rb +282 -115
  153. data/lib/active_record/relation.rb +176 -116
  154. data/lib/active_record/relation/batches.rb +139 -34
  155. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  156. data/lib/active_record/relation/calculations.rb +79 -108
  157. data/lib/active_record/relation/delegation.rb +7 -20
  158. data/lib/active_record/relation/finder_methods.rb +163 -81
  159. data/lib/active_record/relation/from_clause.rb +32 -0
  160. data/lib/active_record/relation/merger.rb +16 -42
  161. data/lib/active_record/relation/predicate_builder.rb +120 -107
  162. data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
  163. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  164. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  165. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  166. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  167. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  168. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  169. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  170. data/lib/active_record/relation/query_attribute.rb +19 -0
  171. data/lib/active_record/relation/query_methods.rb +308 -244
  172. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  173. data/lib/active_record/relation/spawn_methods.rb +4 -7
  174. data/lib/active_record/relation/where_clause.rb +174 -0
  175. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  176. data/lib/active_record/result.rb +4 -3
  177. data/lib/active_record/runtime_registry.rb +1 -1
  178. data/lib/active_record/sanitization.rb +95 -66
  179. data/lib/active_record/schema.rb +26 -22
  180. data/lib/active_record/schema_dumper.rb +62 -38
  181. data/lib/active_record/schema_migration.rb +11 -14
  182. data/lib/active_record/scoping.rb +32 -15
  183. data/lib/active_record/scoping/default.rb +23 -9
  184. data/lib/active_record/scoping/named.rb +49 -28
  185. data/lib/active_record/secure_token.rb +38 -0
  186. data/lib/active_record/serialization.rb +2 -4
  187. data/lib/active_record/statement_cache.rb +16 -14
  188. data/lib/active_record/store.rb +8 -3
  189. data/lib/active_record/suppressor.rb +58 -0
  190. data/lib/active_record/table_metadata.rb +68 -0
  191. data/lib/active_record/tasks/database_tasks.rb +57 -43
  192. data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
  193. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
  194. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  195. data/lib/active_record/timestamp.rb +20 -9
  196. data/lib/active_record/touch_later.rb +58 -0
  197. data/lib/active_record/transactions.rb +138 -56
  198. data/lib/active_record/type.rb +66 -17
  199. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  200. data/lib/active_record/type/date.rb +2 -45
  201. data/lib/active_record/type/date_time.rb +2 -49
  202. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  203. data/lib/active_record/type/internal/timezone.rb +15 -0
  204. data/lib/active_record/type/serialized.rb +15 -14
  205. data/lib/active_record/type/time.rb +10 -16
  206. data/lib/active_record/type/type_map.rb +4 -4
  207. data/lib/active_record/type_caster.rb +7 -0
  208. data/lib/active_record/type_caster/connection.rb +29 -0
  209. data/lib/active_record/type_caster/map.rb +19 -0
  210. data/lib/active_record/validations.rb +33 -32
  211. data/lib/active_record/validations/absence.rb +23 -0
  212. data/lib/active_record/validations/associated.rb +10 -3
  213. data/lib/active_record/validations/length.rb +24 -0
  214. data/lib/active_record/validations/presence.rb +11 -12
  215. data/lib/active_record/validations/uniqueness.rb +30 -29
  216. data/lib/rails/generators/active_record/migration.rb +7 -0
  217. data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
  218. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
  219. data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
  220. data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
  221. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  222. data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
  223. metadata +59 -34
  224. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  225. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  226. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
  227. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  228. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  229. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  230. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  231. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  232. data/lib/active_record/type/big_integer.rb +0 -13
  233. data/lib/active_record/type/binary.rb +0 -50
  234. data/lib/active_record/type/boolean.rb +0 -31
  235. data/lib/active_record/type/decimal.rb +0 -64
  236. data/lib/active_record/type/decimal_without_scale.rb +0 -11
  237. data/lib/active_record/type/decorator.rb +0 -14
  238. data/lib/active_record/type/float.rb +0 -19
  239. data/lib/active_record/type/integer.rb +0 -59
  240. data/lib/active_record/type/mutable.rb +0 -16
  241. data/lib/active_record/type/numeric.rb +0 -36
  242. data/lib/active_record/type/string.rb +0 -40
  243. data/lib/active_record/type/text.rb +0 -11
  244. data/lib/active_record/type/time_value.rb +0 -38
  245. data/lib/active_record/type/unsigned_integer.rb +0 -15
  246. data/lib/active_record/type/value.rb +0 -110
@@ -1,38 +1,57 @@
1
1
  module ActiveRecord
2
2
  module ConnectionAdapters
3
- class StatementPool
3
+ class StatementPool # :nodoc:
4
4
  include Enumerable
5
5
 
6
- def initialize(connection, max = 1000)
7
- @connection = connection
8
- @max = max
6
+ DEFAULT_STATEMENT_LIMIT = 1000
7
+
8
+ def initialize(statement_limit = nil)
9
+ @cache = Hash.new { |h,pid| h[pid] = {} }
10
+ @statement_limit = statement_limit || DEFAULT_STATEMENT_LIMIT
9
11
  end
10
12
 
11
- def each
12
- raise NotImplementedError
13
+ def each(&block)
14
+ cache.each(&block)
13
15
  end
14
16
 
15
17
  def key?(key)
16
- raise NotImplementedError
18
+ cache.key?(key)
17
19
  end
18
20
 
19
21
  def [](key)
20
- raise NotImplementedError
22
+ cache[key]
21
23
  end
22
24
 
23
25
  def length
24
- raise NotImplementedError
26
+ cache.length
25
27
  end
26
28
 
27
- def []=(sql, key)
28
- raise NotImplementedError
29
+ def []=(sql, stmt)
30
+ while @statement_limit <= cache.size
31
+ dealloc(cache.shift.last)
32
+ end
33
+ cache[sql] = stmt
29
34
  end
30
35
 
31
36
  def clear
32
- raise NotImplementedError
37
+ cache.each_value do |stmt|
38
+ dealloc stmt
39
+ end
40
+ cache.clear
33
41
  end
34
42
 
35
43
  def delete(key)
44
+ dealloc cache[key]
45
+ cache.delete(key)
46
+ end
47
+
48
+ private
49
+
50
+ def cache
51
+ @cache[Process.pid]
52
+ end
53
+
54
+ def dealloc(stmt)
36
55
  raise NotImplementedError
37
56
  end
38
57
  end
@@ -5,10 +5,10 @@ module ActiveRecord
5
5
 
6
6
  # Establishes the connection to the database. Accepts a hash as input where
7
7
  # the <tt>:adapter</tt> key must be specified with the name of a database adapter (in lower-case)
8
- # example for regular databases (MySQL, Postgresql, etc):
8
+ # example for regular databases (MySQL, PostgreSQL, etc):
9
9
  #
10
10
  # ActiveRecord::Base.establish_connection(
11
- # adapter: "mysql",
11
+ # adapter: "mysql2",
12
12
  # host: "localhost",
13
13
  # username: "myuser",
14
14
  # password: "mypass",
@@ -35,26 +35,30 @@ module ActiveRecord
35
35
  # "postgres://myuser:mypass@localhost/somedatabase"
36
36
  # )
37
37
  #
38
- # In case <tt>ActiveRecord::Base.configurations</tt> is set (Rails
39
- # automatically loads the contents of config/database.yml into it),
38
+ # In case {ActiveRecord::Base.configurations}[rdoc-ref:Core.configurations]
39
+ # is set (Rails automatically loads the contents of config/database.yml into it),
40
40
  # a symbol can also be given as argument, representing a key in the
41
41
  # configuration hash:
42
42
  #
43
43
  # ActiveRecord::Base.establish_connection(:production)
44
44
  #
45
- # The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
45
+ # The exceptions AdapterNotSpecified, AdapterNotFound and +ArgumentError+
46
46
  # may be returned on an error.
47
47
  def establish_connection(spec = nil)
48
+ raise RuntimeError, "Anonymous class is not allowed." unless name
49
+
48
50
  spec ||= DEFAULT_ENV.call.to_sym
49
51
  resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new configurations
50
- spec = resolver.spec(spec)
52
+ # TODO: uses name on establish_connection, for backwards compatibility
53
+ spec = resolver.spec(spec, self == Base ? "primary" : name)
51
54
 
52
55
  unless respond_to?(spec.adapter_method)
53
56
  raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
54
57
  end
55
58
 
56
- remove_connection
57
- connection_handler.establish_connection self, spec
59
+ remove_connection(spec.name)
60
+ self.connection_specification_name = spec.name
61
+ connection_handler.establish_connection spec
58
62
  end
59
63
 
60
64
  class MergeAndResolveDefaultUrlConfig # :nodoc:
@@ -87,8 +91,19 @@ module ActiveRecord
87
91
  retrieve_connection
88
92
  end
89
93
 
94
+ attr_writer :connection_specification_name
95
+
96
+ # Return the specification id from this class otherwise look it up
97
+ # in the parent.
98
+ def connection_specification_name
99
+ if !defined?(@connection_specification_name) || @connection_specification_name.nil?
100
+ return self == Base ? "primary" : superclass.connection_specification_name
101
+ end
102
+ @connection_specification_name
103
+ end
104
+
90
105
  def connection_id
91
- ActiveRecord::RuntimeRegistry.connection_id
106
+ ActiveRecord::RuntimeRegistry.connection_id ||= Thread.current.object_id
92
107
  end
93
108
 
94
109
  def connection_id=(connection_id)
@@ -106,20 +121,28 @@ module ActiveRecord
106
121
  end
107
122
 
108
123
  def connection_pool
109
- connection_handler.retrieve_connection_pool(self) or raise ConnectionNotEstablished
124
+ connection_handler.retrieve_connection_pool(connection_specification_name) or raise ConnectionNotEstablished
110
125
  end
111
126
 
112
127
  def retrieve_connection
113
- connection_handler.retrieve_connection(self)
128
+ connection_handler.retrieve_connection(connection_specification_name)
114
129
  end
115
130
 
116
131
  # Returns +true+ if Active Record is connected.
117
132
  def connected?
118
- connection_handler.connected?(self)
133
+ connection_handler.connected?(connection_specification_name)
119
134
  end
120
135
 
121
- def remove_connection(klass = self)
122
- connection_handler.remove_connection(klass)
136
+ def remove_connection(name = nil)
137
+ name ||= @connection_specification_name if defined?(@connection_specification_name)
138
+ # if removing a connection that have a pool, we reset the
139
+ # connection_specification_name so it will use the parent
140
+ # pool.
141
+ if connection_handler.retrieve_connection_pool(name)
142
+ self.connection_specification_name = nil
143
+ end
144
+
145
+ connection_handler.remove_connection(name)
123
146
  end
124
147
 
125
148
  def clear_cache! # :nodoc:
@@ -70,6 +70,14 @@ module ActiveRecord
70
70
  mattr_accessor :schema_format, instance_writer: false
71
71
  self.schema_format = :ruby
72
72
 
73
+ ##
74
+ # :singleton-method:
75
+ # Specifies if an error should be raised on query limit or order being
76
+ # ignored when doing batch queries. Useful in applications where the
77
+ # limit or scope being ignored is error-worthy, rather than a warning.
78
+ mattr_accessor :error_on_ignored_order_or_limit, instance_writer: false
79
+ self.error_on_ignored_order_or_limit = false
80
+
73
81
  ##
74
82
  # :singleton-method:
75
83
  # Specify whether or not to use timestamps for migration versions
@@ -85,17 +93,30 @@ module ActiveRecord
85
93
  mattr_accessor :dump_schema_after_migration, instance_writer: false
86
94
  self.dump_schema_after_migration = true
87
95
 
96
+ ##
97
+ # :singleton-method:
98
+ # Specifies which database schemas to dump when calling db:structure:dump.
99
+ # If the value is :schema_search_path (the default), any schemas listed in
100
+ # schema_search_path are dumped. Use :all to dump all schemas regardless
101
+ # of schema_search_path, or a string of comma separated schemas for a
102
+ # custom list.
103
+ mattr_accessor :dump_schemas, instance_writer: false
104
+ self.dump_schemas = :schema_search_path
105
+
106
+ ##
107
+ # :singleton-method:
108
+ # Specify a threshold for the size of query result sets. If the number of
109
+ # records in the set exceeds the threshold, a warning is logged. This can
110
+ # be used to identify queries which load thousands of records and
111
+ # potentially cause memory bloat.
112
+ mattr_accessor :warn_on_records_fetched_greater_than, instance_writer: false
113
+ self.warn_on_records_fetched_greater_than = nil
114
+
88
115
  mattr_accessor :maintain_test_schema, instance_accessor: false
89
116
 
90
- def self.disable_implicit_join_references=(value)
91
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
92
- Implicit join references were removed with Rails 4.1.
93
- Make sure to remove this configuration because it does nothing.
94
- MSG
95
- end
117
+ mattr_accessor :belongs_to_required_by_default, instance_accessor: false
96
118
 
97
119
  class_attribute :default_connection_handler, instance_writer: false
98
- class_attribute :find_by_statement_cache
99
120
 
100
121
  def self.connection_handler
101
122
  ActiveRecord::RuntimeRegistry.connection_handler || default_connection_handler
@@ -115,10 +136,11 @@ module ActiveRecord
115
136
  end
116
137
 
117
138
  def initialize_find_by_cache # :nodoc:
118
- self.find_by_statement_cache = {}.extend(Mutex_m)
139
+ @find_by_statement_cache = { true => {}.extend(Mutex_m), false => {}.extend(Mutex_m) }
119
140
  end
120
141
 
121
142
  def inherited(child_class) # :nodoc:
143
+ # initialize cache at class definition for thread safety
122
144
  child_class.initialize_find_by_cache
123
145
  super
124
146
  end
@@ -126,12 +148,9 @@ module ActiveRecord
126
148
  def find(*ids) # :nodoc:
127
149
  # We don't have cache keys for this stuff yet
128
150
  return super unless ids.length == 1
129
- # Allow symbols to super to maintain compatibility for deprecated finders until Rails 5
130
- return super if ids.first.kind_of?(Symbol)
131
151
  return super if block_given? ||
132
152
  primary_key.nil? ||
133
- default_scopes.any? ||
134
- current_scope ||
153
+ scope_attributes? ||
135
154
  columns_hash.include?(inheritance_column) ||
136
155
  ids.first.kind_of?(Array)
137
156
 
@@ -140,60 +159,57 @@ module ActiveRecord
140
159
  id = id.id
141
160
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
142
161
  You are passing an instance of ActiveRecord::Base to `find`.
143
- Please pass the id of the object by calling `.id`
162
+ Please pass the id of the object by calling `.id`.
144
163
  MSG
145
164
  end
165
+
146
166
  key = primary_key
147
167
 
148
- s = find_by_statement_cache[key] || find_by_statement_cache.synchronize {
149
- find_by_statement_cache[key] ||= StatementCache.create(connection) { |params|
150
- where(key => params.bind).limit(1)
151
- }
168
+ statement = cached_find_by_statement(key) { |params|
169
+ where(key => params.bind).limit(1)
152
170
  }
153
- record = s.execute([id], self, connection).first
171
+ record = statement.execute([id], self, connection).first
154
172
  unless record
155
- raise RecordNotFound, "Couldn't find #{name} with '#{primary_key}'=#{id}"
173
+ raise RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}",
174
+ name, primary_key, id)
156
175
  end
157
176
  record
158
177
  rescue RangeError
159
- raise RecordNotFound, "Couldn't find #{name} with an out of range value for '#{primary_key}'"
178
+ raise RecordNotFound.new("Couldn't find #{name} with an out of range value for '#{primary_key}'",
179
+ name, primary_key)
160
180
  end
161
181
 
162
182
  def find_by(*args) # :nodoc:
163
- return super if current_scope || !(Hash === args.first) || reflect_on_all_aggregations.any?
164
- return super if default_scopes.any?
183
+ return super if scope_attributes? || !(Hash === args.first) || reflect_on_all_aggregations.any?
165
184
 
166
185
  hash = args.first
167
186
 
168
187
  return super if hash.values.any? { |v|
169
- v.nil? || Array === v || Hash === v
188
+ v.nil? || Array === v || Hash === v || Relation === v
170
189
  }
171
190
 
172
191
  # We can't cache Post.find_by(author: david) ...yet
173
192
  return super unless hash.keys.all? { |k| columns_hash.has_key?(k.to_s) }
174
193
 
175
- key = hash.keys
194
+ keys = hash.keys
176
195
 
177
- klass = self
178
- s = find_by_statement_cache[key] || find_by_statement_cache.synchronize {
179
- find_by_statement_cache[key] ||= StatementCache.create(connection) { |params|
180
- wheres = key.each_with_object({}) { |param,o|
181
- o[param] = params.bind
182
- }
183
- klass.where(wheres).limit(1)
196
+ statement = cached_find_by_statement(keys) { |params|
197
+ wheres = keys.each_with_object({}) { |param, o|
198
+ o[param] = params.bind
184
199
  }
200
+ where(wheres).limit(1)
185
201
  }
186
202
  begin
187
- s.execute(hash.values, self, connection).first
188
- rescue TypeError => e
189
- raise ActiveRecord::StatementInvalid.new(e.message, e)
203
+ statement.execute(hash.values, self, connection).first
204
+ rescue TypeError
205
+ raise ActiveRecord::StatementInvalid
190
206
  rescue RangeError
191
207
  nil
192
208
  end
193
209
  end
194
210
 
195
211
  def find_by!(*args) # :nodoc:
196
- find_by(*args) or raise RecordNotFound.new("Couldn't find #{name}")
212
+ find_by(*args) or raise RecordNotFound.new("Couldn't find #{name}", name)
197
213
  end
198
214
 
199
215
  def initialize_generated_modules # :nodoc:
@@ -217,7 +233,7 @@ module ActiveRecord
217
233
  elsif !connected?
218
234
  "#{super} (call '#{super}.connection' to establish a connection)"
219
235
  elsif table_exists?
220
- attr_list = columns.map { |c| "#{c.name}: #{c.type}" } * ', '
236
+ attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ', '
221
237
  "#{super}(#{attr_list})"
222
238
  else
223
239
  "#{super}(Table doesn't exist)"
@@ -235,30 +251,54 @@ module ActiveRecord
235
251
  # scope :published_and_commented, -> { published.and(self.arel_table[:comments_count].gt(0)) }
236
252
  # end
237
253
  def arel_table # :nodoc:
238
- @arel_table ||= Arel::Table.new(table_name, arel_engine)
254
+ @arel_table ||= Arel::Table.new(table_name, type_caster: type_caster)
239
255
  end
240
256
 
241
257
  # Returns the Arel engine.
242
258
  def arel_engine # :nodoc:
243
259
  @arel_engine ||=
244
- if Base == self || connection_handler.retrieve_connection_pool(self)
260
+ if Base == self || connection_handler.retrieve_connection_pool(connection_specification_name)
245
261
  self
246
262
  else
247
263
  superclass.arel_engine
248
264
  end
249
265
  end
250
266
 
267
+ def arel_attribute(name, table = arel_table) # :nodoc:
268
+ name = attribute_alias(name) if attribute_alias?(name)
269
+ table[name]
270
+ end
271
+
272
+ def predicate_builder # :nodoc:
273
+ @predicate_builder ||= PredicateBuilder.new(table_metadata)
274
+ end
275
+
276
+ def type_caster # :nodoc:
277
+ TypeCaster::Map.new(self)
278
+ end
279
+
251
280
  private
252
281
 
253
- def relation #:nodoc:
254
- relation = Relation.create(self, arel_table)
282
+ def cached_find_by_statement(key, &block) # :nodoc:
283
+ cache = @find_by_statement_cache[connection.prepared_statements]
284
+ cache[key] || cache.synchronize {
285
+ cache[key] ||= StatementCache.create(connection, &block)
286
+ }
287
+ end
288
+
289
+ def relation # :nodoc:
290
+ relation = Relation.create(self, arel_table, predicate_builder)
255
291
 
256
- if finder_needs_type_condition?
292
+ if finder_needs_type_condition? && !ignore_default_scope?
257
293
  relation.where(type_condition).create_with(inheritance_column.to_sym => sti_name)
258
294
  else
259
295
  relation
260
296
  end
261
297
  end
298
+
299
+ def table_metadata # :nodoc:
300
+ TableMetadata.new(self, arel_table)
301
+ end
262
302
  end
263
303
 
264
304
  # New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
@@ -269,16 +309,14 @@ module ActiveRecord
269
309
  # ==== Example:
270
310
  # # Instantiates a single new object
271
311
  # User.new(first_name: 'Jamie')
272
- def initialize(attributes = nil, options = {})
273
- @attributes = self.class._default_attributes.dup
312
+ def initialize(attributes = nil)
313
+ @attributes = self.class._default_attributes.deep_dup
274
314
  self.class.define_attribute_methods
275
315
 
276
316
  init_internals
277
317
  initialize_internals_callback
278
318
 
279
- # +options+ argument is only needed to make protected_attributes gem easier to hook.
280
- # Remove it when we drop support to this gem.
281
- init_attributes(attributes, options) if attributes
319
+ assign_attributes(attributes) if attributes
282
320
 
283
321
  yield self if block_given?
284
322
  _run_initialize_callbacks
@@ -286,7 +324,7 @@ module ActiveRecord
286
324
 
287
325
  # Initialize an empty model object from +coder+. +coder+ should be
288
326
  # the result of previously encoding an Active Record model, using
289
- # `encode_with`
327
+ # #encode_with.
290
328
  #
291
329
  # class Post < ActiveRecord::Base
292
330
  # end
@@ -342,14 +380,11 @@ module ActiveRecord
342
380
 
343
381
  ##
344
382
  def initialize_dup(other) # :nodoc:
345
- @attributes = @attributes.dup
383
+ @attributes = @attributes.deep_dup
346
384
  @attributes.reset(self.class.primary_key)
347
385
 
348
386
  _run_initialize_callbacks
349
387
 
350
- @aggregation_cache = {}
351
- @association_cache = {}
352
-
353
388
  @new_record = true
354
389
  @destroyed = false
355
390
 
@@ -358,7 +393,7 @@ module ActiveRecord
358
393
 
359
394
  # Populate +coder+ with attributes about this record that should be
360
395
  # serialized. The structure of +coder+ defined in this method is
361
- # guaranteed to match the structure of +coder+ passed to the +init_with+
396
+ # guaranteed to match the structure of +coder+ passed to the #init_with
362
397
  # method.
363
398
  #
364
399
  # Example:
@@ -373,7 +408,7 @@ module ActiveRecord
373
408
  coder['raw_attributes'] = attributes_before_type_cast
374
409
  coder['attributes'] = @attributes
375
410
  coder['new_record'] = new_record?
376
- coder['active_record_yaml_version'] = 0
411
+ coder['active_record_yaml_version'] = 1
377
412
  end
378
413
 
379
414
  # Returns true if +comparison_object+ is the same exact object, or +comparison_object+
@@ -456,7 +491,7 @@ module ActiveRecord
456
491
  "#<#{self.class} #{inspection}>"
457
492
  end
458
493
 
459
- # Takes a PP and prettily prints this record to it, allowing you to get a nice result from `pp record`
494
+ # Takes a PP and prettily prints this record to it, allowing you to get a nice result from <tt>pp record</tt>
460
495
  # when pp is required.
461
496
  def pretty_print(pp)
462
497
  return super if custom_inspect_method_defined?
@@ -487,51 +522,6 @@ module ActiveRecord
487
522
 
488
523
  private
489
524
 
490
- def set_transaction_state(state) # :nodoc:
491
- @transaction_state = state
492
- end
493
-
494
- def has_transactional_callbacks? # :nodoc:
495
- !_rollback_callbacks.empty? || !_commit_callbacks.empty?
496
- end
497
-
498
- # Updates the attributes on this particular ActiveRecord object so that
499
- # if it is associated with a transaction, then the state of the AR object
500
- # will be updated to reflect the current state of the transaction
501
- #
502
- # The @transaction_state variable stores the states of the associated
503
- # transaction. This relies on the fact that a transaction can only be in
504
- # one rollback or commit (otherwise a list of states would be required)
505
- # Each AR object inside of a transaction carries that transaction's
506
- # TransactionState.
507
- #
508
- # This method checks to see if the ActiveRecord object's state reflects
509
- # the TransactionState, and rolls back or commits the ActiveRecord object
510
- # as appropriate.
511
- #
512
- # Since ActiveRecord objects can be inside multiple transactions, this
513
- # method recursively goes through the parent of the TransactionState and
514
- # checks if the ActiveRecord object reflects the state of the object.
515
- def sync_with_transaction_state
516
- update_attributes_from_transaction_state(@transaction_state, 0)
517
- end
518
-
519
- def update_attributes_from_transaction_state(transaction_state, depth)
520
- @reflects_state = [false] if depth == 0
521
-
522
- if transaction_state && transaction_state.finalized? && !has_transactional_callbacks?
523
- unless @reflects_state[depth]
524
- restore_transaction_record_state if transaction_state.rolledback?
525
- clear_transaction_record_state
526
- @reflects_state[depth] = true
527
- end
528
-
529
- if transaction_state.parent && !@reflects_state[depth+1]
530
- update_attributes_from_transaction_state(transaction_state.parent, depth+1)
531
- end
532
- end
533
- end
534
-
535
525
  # Under Ruby 1.9, Array#flatten will call #to_ary (recursively) on each of the elements
536
526
  # of the array, and then rescues from the possible NoMethodError. If those elements are
537
527
  # ActiveRecord::Base's, then this triggers the various method_missing's that we have,
@@ -545,8 +535,6 @@ module ActiveRecord
545
535
  end
546
536
 
547
537
  def init_internals
548
- @aggregation_cache = {}
549
- @association_cache = {}
550
538
  @readonly = false
551
539
  @destroyed = false
552
540
  @marked_for_destruction = false
@@ -560,12 +548,6 @@ module ActiveRecord
560
548
  def initialize_internals_callback
561
549
  end
562
550
 
563
- # This method is needed to make protected_attributes gem easier to hook.
564
- # Remove it when we drop support to this gem.
565
- def init_attributes(attributes, options)
566
- assign_attributes(attributes)
567
- end
568
-
569
551
  def thaw
570
552
  if frozen?
571
553
  @attributes = @attributes.dup