activerecord 4.2.11.3 → 5.0.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 (229) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1029 -1349
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -7
  5. data/examples/performance.rb +2 -2
  6. data/lib/active_record.rb +7 -3
  7. data/lib/active_record/aggregations.rb +35 -25
  8. data/lib/active_record/association_relation.rb +2 -2
  9. data/lib/active_record/associations.rb +305 -204
  10. data/lib/active_record/associations/alias_tracker.rb +19 -16
  11. data/lib/active_record/associations/association.rb +10 -8
  12. data/lib/active_record/associations/association_scope.rb +73 -102
  13. data/lib/active_record/associations/belongs_to_association.rb +20 -32
  14. data/lib/active_record/associations/builder/association.rb +28 -34
  15. data/lib/active_record/associations/builder/belongs_to.rb +41 -18
  16. data/lib/active_record/associations/builder/collection_association.rb +8 -24
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +11 -11
  18. data/lib/active_record/associations/builder/has_many.rb +4 -4
  19. data/lib/active_record/associations/builder/has_one.rb +10 -5
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -9
  21. data/lib/active_record/associations/collection_association.rb +40 -43
  22. data/lib/active_record/associations/collection_proxy.rb +55 -29
  23. data/lib/active_record/associations/foreign_association.rb +1 -1
  24. data/lib/active_record/associations/has_many_association.rb +20 -71
  25. data/lib/active_record/associations/has_many_through_association.rb +8 -52
  26. data/lib/active_record/associations/has_one_association.rb +12 -5
  27. data/lib/active_record/associations/join_dependency.rb +28 -18
  28. data/lib/active_record/associations/join_dependency/join_association.rb +13 -12
  29. data/lib/active_record/associations/preloader.rb +13 -4
  30. data/lib/active_record/associations/preloader/association.rb +45 -51
  31. data/lib/active_record/associations/preloader/collection_association.rb +0 -6
  32. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  33. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  34. data/lib/active_record/associations/preloader/through_association.rb +5 -4
  35. data/lib/active_record/associations/singular_association.rb +6 -0
  36. data/lib/active_record/associations/through_association.rb +11 -3
  37. data/lib/active_record/attribute.rb +61 -17
  38. data/lib/active_record/attribute/user_provided_default.rb +23 -0
  39. data/lib/active_record/attribute_assignment.rb +27 -140
  40. data/lib/active_record/attribute_decorators.rb +6 -5
  41. data/lib/active_record/attribute_methods.rb +79 -26
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  43. data/lib/active_record/attribute_methods/dirty.rb +46 -86
  44. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  45. data/lib/active_record/attribute_methods/query.rb +2 -2
  46. data/lib/active_record/attribute_methods/read.rb +26 -42
  47. data/lib/active_record/attribute_methods/serialization.rb +13 -16
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +42 -9
  49. data/lib/active_record/attribute_methods/write.rb +13 -24
  50. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  51. data/lib/active_record/attribute_set.rb +30 -3
  52. data/lib/active_record/attribute_set/builder.rb +6 -4
  53. data/lib/active_record/attributes.rb +194 -81
  54. data/lib/active_record/autosave_association.rb +33 -15
  55. data/lib/active_record/base.rb +30 -18
  56. data/lib/active_record/callbacks.rb +36 -40
  57. data/lib/active_record/coders/yaml_column.rb +20 -8
  58. data/lib/active_record/collection_cache_key.rb +31 -0
  59. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +431 -122
  60. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  61. data/lib/active_record/connection_adapters/abstract/database_statements.rb +40 -22
  62. data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -8
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +46 -38
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +229 -185
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +52 -13
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +275 -115
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +32 -33
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -32
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +384 -221
  70. data/lib/active_record/connection_adapters/column.rb +27 -41
  71. data/lib/active_record/connection_adapters/connection_specification.rb +2 -21
  72. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  73. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +57 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +69 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +59 -0
  76. data/lib/active_record/connection_adapters/mysql2_adapter.rb +22 -101
  77. data/lib/active_record/connection_adapters/postgresql/column.rb +6 -10
  78. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +3 -3
  79. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  80. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +23 -57
  81. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
  84. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
  85. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
  86. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  87. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  90. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +23 -16
  92. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
  93. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  96. data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -11
  97. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  98. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  99. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +54 -0
  100. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +174 -128
  101. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  102. data/lib/active_record/connection_adapters/postgresql_adapter.rb +184 -112
  103. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  104. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  105. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +15 -0
  106. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +134 -110
  107. data/lib/active_record/connection_adapters/statement_pool.rb +28 -11
  108. data/lib/active_record/connection_handling.rb +5 -5
  109. data/lib/active_record/core.rb +72 -104
  110. data/lib/active_record/counter_cache.rb +9 -20
  111. data/lib/active_record/dynamic_matchers.rb +1 -20
  112. data/lib/active_record/enum.rb +110 -76
  113. data/lib/active_record/errors.rb +72 -47
  114. data/lib/active_record/explain_registry.rb +1 -1
  115. data/lib/active_record/explain_subscriber.rb +1 -1
  116. data/lib/active_record/fixture_set/file.rb +19 -4
  117. data/lib/active_record/fixtures.rb +76 -40
  118. data/lib/active_record/gem_version.rb +4 -4
  119. data/lib/active_record/inheritance.rb +27 -40
  120. data/lib/active_record/integration.rb +4 -4
  121. data/lib/active_record/legacy_yaml_adapter.rb +18 -2
  122. data/lib/active_record/locale/en.yml +3 -2
  123. data/lib/active_record/locking/optimistic.rb +10 -14
  124. data/lib/active_record/locking/pessimistic.rb +1 -1
  125. data/lib/active_record/log_subscriber.rb +40 -22
  126. data/lib/active_record/migration.rb +304 -133
  127. data/lib/active_record/migration/command_recorder.rb +59 -18
  128. data/lib/active_record/migration/compatibility.rb +90 -0
  129. data/lib/active_record/model_schema.rb +92 -40
  130. data/lib/active_record/nested_attributes.rb +45 -34
  131. data/lib/active_record/null_relation.rb +15 -7
  132. data/lib/active_record/persistence.rb +112 -72
  133. data/lib/active_record/querying.rb +6 -5
  134. data/lib/active_record/railtie.rb +20 -13
  135. data/lib/active_record/railties/controller_runtime.rb +1 -1
  136. data/lib/active_record/railties/databases.rake +47 -38
  137. data/lib/active_record/readonly_attributes.rb +1 -1
  138. data/lib/active_record/reflection.rb +182 -57
  139. data/lib/active_record/relation.rb +152 -100
  140. data/lib/active_record/relation/batches.rb +133 -33
  141. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  142. data/lib/active_record/relation/calculations.rb +80 -101
  143. data/lib/active_record/relation/delegation.rb +6 -19
  144. data/lib/active_record/relation/finder_methods.rb +58 -46
  145. data/lib/active_record/relation/from_clause.rb +32 -0
  146. data/lib/active_record/relation/merger.rb +13 -42
  147. data/lib/active_record/relation/predicate_builder.rb +99 -105
  148. data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
  149. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +78 -0
  150. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  151. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  152. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  153. data/lib/active_record/relation/predicate_builder/range_handler.rb +17 -0
  154. data/lib/active_record/relation/query_attribute.rb +19 -0
  155. data/lib/active_record/relation/query_methods.rb +274 -238
  156. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  157. data/lib/active_record/relation/spawn_methods.rb +3 -6
  158. data/lib/active_record/relation/where_clause.rb +173 -0
  159. data/lib/active_record/relation/where_clause_factory.rb +37 -0
  160. data/lib/active_record/result.rb +4 -3
  161. data/lib/active_record/runtime_registry.rb +1 -1
  162. data/lib/active_record/sanitization.rb +94 -65
  163. data/lib/active_record/schema.rb +23 -22
  164. data/lib/active_record/schema_dumper.rb +33 -22
  165. data/lib/active_record/schema_migration.rb +10 -4
  166. data/lib/active_record/scoping.rb +17 -6
  167. data/lib/active_record/scoping/default.rb +19 -6
  168. data/lib/active_record/scoping/named.rb +39 -28
  169. data/lib/active_record/secure_token.rb +38 -0
  170. data/lib/active_record/serialization.rb +2 -4
  171. data/lib/active_record/statement_cache.rb +15 -13
  172. data/lib/active_record/store.rb +8 -3
  173. data/lib/active_record/suppressor.rb +54 -0
  174. data/lib/active_record/table_metadata.rb +64 -0
  175. data/lib/active_record/tasks/database_tasks.rb +30 -40
  176. data/lib/active_record/tasks/mysql_database_tasks.rb +7 -15
  177. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
  178. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  179. data/lib/active_record/timestamp.rb +16 -9
  180. data/lib/active_record/touch_later.rb +58 -0
  181. data/lib/active_record/transactions.rb +138 -56
  182. data/lib/active_record/type.rb +66 -17
  183. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  184. data/lib/active_record/type/date.rb +2 -45
  185. data/lib/active_record/type/date_time.rb +2 -49
  186. data/lib/active_record/type/internal/abstract_json.rb +33 -0
  187. data/lib/active_record/type/internal/timezone.rb +15 -0
  188. data/lib/active_record/type/serialized.rb +9 -14
  189. data/lib/active_record/type/time.rb +3 -21
  190. data/lib/active_record/type/type_map.rb +4 -4
  191. data/lib/active_record/type_caster.rb +7 -0
  192. data/lib/active_record/type_caster/connection.rb +29 -0
  193. data/lib/active_record/type_caster/map.rb +19 -0
  194. data/lib/active_record/validations.rb +33 -32
  195. data/lib/active_record/validations/absence.rb +24 -0
  196. data/lib/active_record/validations/associated.rb +10 -3
  197. data/lib/active_record/validations/length.rb +36 -0
  198. data/lib/active_record/validations/presence.rb +12 -12
  199. data/lib/active_record/validations/uniqueness.rb +24 -21
  200. data/lib/rails/generators/active_record/migration.rb +7 -0
  201. data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
  202. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
  203. data/lib/rails/generators/active_record/migration/templates/migration.rb +4 -1
  204. data/lib/rails/generators/active_record/model/model_generator.rb +21 -15
  205. data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
  206. metadata +50 -35
  207. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  208. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  209. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
  210. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  211. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  212. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  213. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  214. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  215. data/lib/active_record/type/big_integer.rb +0 -13
  216. data/lib/active_record/type/binary.rb +0 -50
  217. data/lib/active_record/type/boolean.rb +0 -31
  218. data/lib/active_record/type/decimal.rb +0 -64
  219. data/lib/active_record/type/decimal_without_scale.rb +0 -11
  220. data/lib/active_record/type/decorator.rb +0 -14
  221. data/lib/active_record/type/float.rb +0 -19
  222. data/lib/active_record/type/integer.rb +0 -59
  223. data/lib/active_record/type/mutable.rb +0 -16
  224. data/lib/active_record/type/numeric.rb +0 -36
  225. data/lib/active_record/type/string.rb +0 -40
  226. data/lib/active_record/type/text.rb +0 -11
  227. data/lib/active_record/type/time_value.rb +0 -38
  228. data/lib/active_record/type/unsigned_integer.rb +0 -15
  229. data/lib/active_record/type/value.rb +0 -110
@@ -0,0 +1,38 @@
1
+ module ActiveRecord
2
+ module SecureToken
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ # Example using #has_secure_token
7
+ #
8
+ # # Schema: User(token:string, auth_token:string)
9
+ # class User < ActiveRecord::Base
10
+ # has_secure_token
11
+ # has_secure_token :auth_token
12
+ # end
13
+ #
14
+ # user = User.new
15
+ # user.save
16
+ # user.token # => "pX27zsMN2ViQKta1bGfLmVJE"
17
+ # user.auth_token # => "77TMHrHJFvFDwodq8w7Ev2m7"
18
+ # user.regenerate_token # => true
19
+ # user.regenerate_auth_token # => true
20
+ #
21
+ # <tt>SecureRandom::base58</tt> is used to generate the 24-character unique token, so collisions are highly unlikely.
22
+ #
23
+ # Note that it's still possible to generate a race condition in the database in the same way that
24
+ # {validates_uniqueness_of}[rdoc-ref:Validations::ClassMethods#validates_uniqueness_of] can.
25
+ # You're encouraged to add a unique index in the database to deal with this even more unlikely scenario.
26
+ def has_secure_token(attribute = :token)
27
+ # Load securerandom only when has_secure_token is used.
28
+ require 'active_support/core_ext/securerandom'
29
+ define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token }
30
+ before_create { self.send("#{attribute}=", self.class.generate_unique_secure_token) unless self.send("#{attribute}?")}
31
+ end
32
+
33
+ def generate_unique_secure_token
34
+ SecureRandom.base58(24)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord #:nodoc:
2
- # = Active Record Serialization
2
+ # = Active Record \Serialization
3
3
  module Serialization
4
4
  extend ActiveSupport::Concern
5
5
  include ActiveModel::Serializers::JSON
@@ -11,12 +11,10 @@ module ActiveRecord #:nodoc:
11
11
  def serializable_hash(options = nil)
12
12
  options = options.try(:clone) || {}
13
13
 
14
- options[:except] = Array(options[:except]).map { |n| n.to_s }
14
+ options[:except] = Array(options[:except]).map(&:to_s)
15
15
  options[:except] |= Array(self.class.inheritance_column)
16
16
 
17
17
  super(options)
18
18
  end
19
19
  end
20
20
  end
21
-
22
- require 'active_record/serializers/xml_serializer'
@@ -7,12 +7,14 @@ module ActiveRecord
7
7
  # Book.where(name: "my book").where("author_id > 3")
8
8
  # end
9
9
  #
10
- # The cached statement is executed by using the +execute+ method:
10
+ # The cached statement is executed by using the
11
+ # [connection.execute]{rdoc-ref:ConnectionAdapters::DatabaseStatements#execute} method:
11
12
  #
12
13
  # cache.execute([], Book, Book.connection)
13
14
  #
14
- # The relation returned by the block is cached, and for each +execute+ call the cached relation gets duped.
15
- # Database is queried when +to_a+ is called on the relation.
15
+ # The relation returned by the block is cached, and for each
16
+ # [execute]{rdoc-ref:ConnectionAdapters::DatabaseStatements#execute}
17
+ # call the cached relation gets duped. Database is queried when +to_a+ is called on the relation.
16
18
  #
17
19
  # If you want to cache the statement without the values you can use the +bind+ method of the
18
20
  # block parameter.
@@ -47,8 +49,8 @@ module ActiveRecord
47
49
 
48
50
  def sql_for(binds, connection)
49
51
  val = @values.dup
50
- binds = binds.dup
51
- @indexes.each { |i| val[i] = connection.quote(*binds.shift.reverse) }
52
+ binds = connection.prepare_binds_for_database(binds)
53
+ @indexes.each { |i| val[i] = connection.quote(binds.shift) }
52
54
  val.join
53
55
  end
54
56
  end
@@ -67,21 +69,21 @@ module ActiveRecord
67
69
  end
68
70
 
69
71
  class BindMap # :nodoc:
70
- def initialize(bind_values)
72
+ def initialize(bound_attributes)
71
73
  @indexes = []
72
- @bind_values = bind_values
74
+ @bound_attributes = bound_attributes
73
75
 
74
- bind_values.each_with_index do |(_, value), i|
75
- if Substitute === value
76
+ bound_attributes.each_with_index do |attr, i|
77
+ if Substitute === attr.value
76
78
  @indexes << i
77
79
  end
78
80
  end
79
81
  end
80
82
 
81
83
  def bind(values)
82
- bvs = @bind_values.map { |pair| pair.dup }
83
- @indexes.each_with_index { |offset,i| bvs[offset][1] = values[i] }
84
- bvs
84
+ bas = @bound_attributes.dup
85
+ @indexes.each_with_index { |offset,i| bas[offset] = bas[offset].with_cast_value(values[i]) }
86
+ bas
85
87
  end
86
88
  end
87
89
 
@@ -89,7 +91,7 @@ module ActiveRecord
89
91
 
90
92
  def self.create(connection, block = Proc.new)
91
93
  relation = block.call Params.new
92
- bind_map = BindMap.new relation.bind_values
94
+ bind_map = BindMap.new relation.bound_attributes
93
95
  query_builder = connection.cacheable_query relation.arel
94
96
  new query_builder, bind_map
95
97
  end
@@ -15,11 +15,16 @@ module ActiveRecord
15
15
  # You can set custom coder to encode/decode your serialized attributes to/from different formats.
16
16
  # JSON, YAML, Marshal are supported out of the box. Generally it can be any wrapper that provides +load+ and +dump+.
17
17
  #
18
- # NOTE - If you are using PostgreSQL specific columns like +hstore+ or +json+ there is no need for
19
- # the serialization provided by +store+. Simply use +store_accessor+ instead to generate
18
+ # NOTE: If you are using PostgreSQL specific columns like +hstore+ or +json+ there is no need for
19
+ # the serialization provided by {.store}[rdoc-ref:rdoc-ref:ClassMethods#store].
20
+ # Simply use {.store_accessor}[rdoc-ref:ClassMethods#store_accessor] instead to generate
20
21
  # the accessor methods. Be aware that these columns use a string keyed hash and do not allow access
21
22
  # using a symbol.
22
23
  #
24
+ # NOTE: The default validations with the exception of +uniqueness+ will work.
25
+ # For example, if you want to check for +uniqueness+ with +hstore+ you will
26
+ # need to use a custom validation to handle it.
27
+ #
23
28
  # Examples:
24
29
  #
25
30
  # class User < ActiveRecord::Base
@@ -39,7 +44,7 @@ module ActiveRecord
39
44
  # store_accessor :settings, :privileges, :servants
40
45
  # end
41
46
  #
42
- # The stored attribute names can be retrieved using +stored_attributes+.
47
+ # The stored attribute names can be retrieved using {.stored_attributes}[rdoc-ref:rdoc-ref:ClassMethods#stored_attributes].
43
48
  #
44
49
  # User.stored_attributes[:settings] # [:color, :homepage]
45
50
  #
@@ -0,0 +1,54 @@
1
+ module ActiveRecord
2
+ # ActiveRecord::Suppressor prevents the receiver from being saved during
3
+ # a given block.
4
+ #
5
+ # For example, here's a pattern of creating notifications when new comments
6
+ # are posted. (The notification may in turn trigger an email, a push
7
+ # notification, or just appear in the UI somewhere):
8
+ #
9
+ # class Comment < ActiveRecord::Base
10
+ # belongs_to :commentable, polymorphic: true
11
+ # after_create -> { Notification.create! comment: self,
12
+ # recipients: commentable.recipients }
13
+ # end
14
+ #
15
+ # That's what you want the bulk of the time. New comment creates a new
16
+ # Notification. But there may well be off cases, like copying a commentable
17
+ # and its comments, where you don't want that. So you'd have a concern
18
+ # something like this:
19
+ #
20
+ # module Copyable
21
+ # def copy_to(destination)
22
+ # Notification.suppress do
23
+ # # Copy logic that creates new comments that we do not want
24
+ # # triggering notifications.
25
+ # end
26
+ # end
27
+ # end
28
+ module Suppressor
29
+ extend ActiveSupport::Concern
30
+
31
+ module ClassMethods
32
+ def suppress(&block)
33
+ SuppressorRegistry.suppressed[name] = true
34
+ yield
35
+ ensure
36
+ SuppressorRegistry.suppressed[name] = false
37
+ end
38
+ end
39
+
40
+ def create_or_update(*args) # :nodoc:
41
+ SuppressorRegistry.suppressed[self.class.name] ? true : super
42
+ end
43
+ end
44
+
45
+ class SuppressorRegistry # :nodoc:
46
+ extend ActiveSupport::PerThreadRegistry
47
+
48
+ attr_reader :suppressed
49
+
50
+ def initialize
51
+ @suppressed = {}
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,64 @@
1
+ module ActiveRecord
2
+ class TableMetadata # :nodoc:
3
+ delegate :foreign_type, :foreign_key, to: :association, prefix: true
4
+ delegate :association_primary_key, to: :association
5
+
6
+ def initialize(klass, arel_table, association = nil)
7
+ @klass = klass
8
+ @arel_table = arel_table
9
+ @association = association
10
+ end
11
+
12
+ def resolve_column_aliases(hash)
13
+ # This method is a hot spot, so for now, use Hash[] to dup the hash.
14
+ # https://bugs.ruby-lang.org/issues/7166
15
+ new_hash = Hash[hash]
16
+ hash.each do |key, _|
17
+ if (key.is_a?(Symbol)) && klass.attribute_alias?(key)
18
+ new_hash[klass.attribute_alias(key)] = new_hash.delete(key)
19
+ end
20
+ end
21
+ new_hash
22
+ end
23
+
24
+ def arel_attribute(column_name)
25
+ arel_table[column_name]
26
+ end
27
+
28
+ def type(column_name)
29
+ if klass
30
+ klass.type_for_attribute(column_name.to_s)
31
+ else
32
+ Type::Value.new
33
+ end
34
+ end
35
+
36
+ def associated_with?(association_name)
37
+ klass && klass._reflect_on_association(association_name)
38
+ end
39
+
40
+ def associated_table(table_name)
41
+ return self if table_name == arel_table.name
42
+
43
+ association = klass._reflect_on_association(table_name)
44
+ if association && !association.polymorphic?
45
+ association_klass = association.klass
46
+ arel_table = association_klass.arel_table.alias(table_name)
47
+ else
48
+ type_caster = TypeCaster::Connection.new(klass, table_name)
49
+ association_klass = nil
50
+ arel_table = Arel::Table.new(table_name, type_caster: type_caster)
51
+ end
52
+
53
+ TableMetadata.new(association_klass, arel_table, association)
54
+ end
55
+
56
+ def polymorphic_association?
57
+ association && association.polymorphic?
58
+ end
59
+
60
+ protected
61
+
62
+ attr_reader :klass, :arel_table, :association
63
+ end
64
+ end
@@ -5,7 +5,7 @@ module ActiveRecord
5
5
  class DatabaseAlreadyExists < StandardError; end # :nodoc:
6
6
  class DatabaseNotSupported < StandardError; end # :nodoc:
7
7
 
8
- # <tt>ActiveRecord::Tasks::DatabaseTasks</tt> is a utility class, which encapsulates
8
+ # ActiveRecord::Tasks::DatabaseTasks is a utility class, which encapsulates
9
9
  # logic behind common tasks used to manage database and migrations.
10
10
  #
11
11
  # The tasks defined here are used with Rake tasks provided by Active Record.
@@ -18,15 +18,15 @@ module ActiveRecord
18
18
  #
19
19
  # The possible config values are:
20
20
  #
21
- # * +env+: current environment (like Rails.env).
22
- # * +database_configuration+: configuration of your databases (as in +config/database.yml+).
23
- # * +db_dir+: your +db+ directory.
24
- # * +fixtures_path+: a path to fixtures directory.
25
- # * +migrations_paths+: a list of paths to directories with migrations.
26
- # * +seed_loader+: an object which will load seeds, it needs to respond to the +load_seed+ method.
27
- # * +root+: a path to the root of the application.
21
+ # * +env+: current environment (like Rails.env).
22
+ # * +database_configuration+: configuration of your databases (as in +config/database.yml+).
23
+ # * +db_dir+: your +db+ directory.
24
+ # * +fixtures_path+: a path to fixtures directory.
25
+ # * +migrations_paths+: a list of paths to directories with migrations.
26
+ # * +seed_loader+: an object which will load seeds, it needs to respond to the +load_seed+ method.
27
+ # * +root+: a path to the root of the application.
28
28
  #
29
- # Example usage of +DatabaseTasks+ outside Rails could look as such:
29
+ # Example usage of DatabaseTasks outside Rails could look as such:
30
30
  #
31
31
  # include ActiveRecord::Tasks
32
32
  # DatabaseTasks.database_configuration = YAML.load_file('my_database_config.yml')
@@ -94,8 +94,9 @@ module ActiveRecord
94
94
  rescue DatabaseAlreadyExists
95
95
  $stderr.puts "#{configuration['database']} already exists"
96
96
  rescue Exception => error
97
- $stderr.puts error, *(error.backtrace)
97
+ $stderr.puts error
98
98
  $stderr.puts "Couldn't create database for #{configuration.inspect}"
99
+ raise
99
100
  end
100
101
 
101
102
  def create_all
@@ -115,8 +116,9 @@ module ActiveRecord
115
116
  rescue ActiveRecord::NoDatabaseError
116
117
  $stderr.puts "Database '#{configuration['database']}' does not exist"
117
118
  rescue Exception => error
118
- $stderr.puts error, *(error.backtrace)
119
+ $stderr.puts error
119
120
  $stderr.puts "Couldn't drop #{configuration['database']}"
121
+ raise
120
122
  end
121
123
 
122
124
  def drop_all
@@ -130,8 +132,6 @@ module ActiveRecord
130
132
  end
131
133
 
132
134
  def migrate
133
- raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
134
-
135
135
  verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
136
136
  version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
137
137
  scope = ENV['SCOPE']
@@ -139,7 +139,6 @@ module ActiveRecord
139
139
  Migrator.migrate(migrations_paths, version) do |migration|
140
140
  scope.blank? || scope == migration.scope
141
141
  end
142
- ActiveRecord::Base.clear_cache!
143
142
  ensure
144
143
  Migration.verbose = verbose_was
145
144
  end
@@ -191,27 +190,7 @@ module ActiveRecord
191
190
  class_for_adapter(configuration['adapter']).new(*arguments).structure_load(filename)
192
191
  end
193
192
 
194
- def load_schema(format = ActiveRecord::Base.schema_format, file = nil)
195
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
196
- This method will act on a specific connection in the future.
197
- To act on the current connection, use `load_schema_current` instead.
198
- MSG
199
-
200
- load_schema_current(format, file)
201
- end
202
-
203
- def schema_file(format = ActiveRecord::Base.schema_format)
204
- case format
205
- when :ruby
206
- File.join(db_dir, "schema.rb")
207
- when :sql
208
- File.join(db_dir, "structure.sql")
209
- end
210
- end
211
-
212
- # This method is the successor of +load_schema+. We should rename it
213
- # after +load_schema+ went through a deprecation cycle. (Rails > 4.2)
214
- def load_schema_for(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
193
+ def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
215
194
  file ||= schema_file(format)
216
195
 
217
196
  case format
@@ -227,22 +206,33 @@ module ActiveRecord
227
206
  end
228
207
  end
229
208
 
230
- def load_schema_current_if_exists(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
231
- if File.exist?(file || schema_file(format))
232
- load_schema_current(format, file, environment)
209
+ def load_schema_for(*args)
210
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
211
+ This method was renamed to `#load_schema` and will be removed in the future.
212
+ Use `#load_schema` instead.
213
+ MSG
214
+ load_schema(*args)
215
+ end
216
+
217
+ def schema_file(format = ActiveRecord::Base.schema_format)
218
+ case format
219
+ when :ruby
220
+ File.join(db_dir, "schema.rb")
221
+ when :sql
222
+ File.join(db_dir, "structure.sql")
233
223
  end
234
224
  end
235
225
 
236
226
  def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
237
227
  each_current_configuration(environment) { |configuration|
238
- load_schema_for configuration, format, file
228
+ load_schema configuration, format, file
239
229
  }
240
230
  ActiveRecord::Base.establish_connection(environment.to_sym)
241
231
  end
242
232
 
243
233
  def check_schema_file(filename)
244
234
  unless File.exist?(filename)
245
- message = %{#{filename} doesn't exist yet. Run `rake db:migrate` to create it, then try again.}
235
+ message = %{#{filename} doesn't exist yet. Run `rails db:migrate` to create it, then try again.}
246
236
  message << %{ If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded.} if defined?(::Rails)
247
237
  Kernel.abort message
248
238
  end
@@ -1,8 +1,6 @@
1
1
  module ActiveRecord
2
2
  module Tasks # :nodoc:
3
3
  class MySQLDatabaseTasks # :nodoc:
4
- DEFAULT_CHARSET = ENV['CHARSET'] || 'utf8'
5
- DEFAULT_COLLATION = ENV['COLLATION'] || 'utf8_unicode_ci'
6
4
  ACCESS_DENIED_ERROR = 1045
7
5
 
8
6
  delegate :connection, :establish_connection, to: ActiveRecord::Base
@@ -23,7 +21,7 @@ module ActiveRecord
23
21
  end
24
22
  rescue error_class => error
25
23
  if error.respond_to?(:errno) && error.errno == ACCESS_DENIED_ERROR
26
- $stdout.print error.error
24
+ $stdout.print error.message
27
25
  establish_connection root_configuration_without_database
28
26
  connection.create_database configuration['database'], creation_options
29
27
  if configuration['username'] != 'root'
@@ -59,6 +57,7 @@ module ActiveRecord
59
57
  args = prepare_command_options
60
58
  args.concat(["--result-file", "#{filename}"])
61
59
  args.concat(["--no-data"])
60
+ args.concat(["--routines"])
62
61
  args.concat(["#{configuration['database']}"])
63
62
 
64
63
  run_cmd('mysqldump', args, 'dumping')
@@ -86,12 +85,6 @@ module ActiveRecord
86
85
  Hash.new.tap do |options|
87
86
  options[:charset] = configuration['encoding'] if configuration.include? 'encoding'
88
87
  options[:collation] = configuration['collation'] if configuration.include? 'collation'
89
-
90
- # Set default charset only when collation isn't set.
91
- options[:charset] ||= DEFAULT_CHARSET unless options[:collation]
92
-
93
- # Set default collation only when charset is also default.
94
- options[:collation] ||= DEFAULT_COLLATION if options[:charset] == DEFAULT_CHARSET
95
88
  end
96
89
  end
97
90
 
@@ -101,8 +94,6 @@ module ActiveRecord
101
94
  ArJdbcMySQL::Error
102
95
  elsif defined?(Mysql2)
103
96
  Mysql2::Error
104
- elsif defined?(Mysql)
105
- Mysql::Error
106
97
  else
107
98
  StandardError
108
99
  end
@@ -129,7 +120,7 @@ IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
129
120
  end
130
121
 
131
122
  def prepare_command_options
132
- {
123
+ args = {
133
124
  'host' => '--host',
134
125
  'port' => '--port',
135
126
  'socket' => '--socket',
@@ -139,9 +130,11 @@ IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
139
130
  'sslca' => '--ssl-ca',
140
131
  'sslcert' => '--ssl-cert',
141
132
  'sslcapath' => '--ssl-capath',
142
- 'sslcipher' => '--ssl-cipher',
133
+ 'sslcipher' => '--ssh-cipher',
143
134
  'sslkey' => '--ssl-key'
144
135
  }.map { |opt, arg| "#{arg}=#{configuration[opt]}" if configuration[opt] }.compact
136
+
137
+ args
145
138
  end
146
139
 
147
140
  def run_cmd(cmd, args, action)
@@ -149,8 +142,7 @@ IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
149
142
  end
150
143
 
151
144
  def run_cmd_error(cmd, args, action)
152
- msg = "failed to execute:\n"
153
- msg << "#{cmd}"
145
+ msg = "failed to execute: `#{cmd}`\n"
154
146
  msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
155
147
  msg
156
148
  end