activerecord 5.2.3

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 (244) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +937 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +217 -0
  5. data/examples/performance.rb +185 -0
  6. data/examples/simple.rb +15 -0
  7. data/lib/active_record.rb +188 -0
  8. data/lib/active_record/aggregations.rb +283 -0
  9. data/lib/active_record/association_relation.rb +40 -0
  10. data/lib/active_record/associations.rb +1860 -0
  11. data/lib/active_record/associations/alias_tracker.rb +81 -0
  12. data/lib/active_record/associations/association.rb +299 -0
  13. data/lib/active_record/associations/association_scope.rb +168 -0
  14. data/lib/active_record/associations/belongs_to_association.rb +130 -0
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +40 -0
  16. data/lib/active_record/associations/builder/association.rb +140 -0
  17. data/lib/active_record/associations/builder/belongs_to.rb +163 -0
  18. data/lib/active_record/associations/builder/collection_association.rb +82 -0
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +135 -0
  20. data/lib/active_record/associations/builder/has_many.rb +17 -0
  21. data/lib/active_record/associations/builder/has_one.rb +30 -0
  22. data/lib/active_record/associations/builder/singular_association.rb +42 -0
  23. data/lib/active_record/associations/collection_association.rb +513 -0
  24. data/lib/active_record/associations/collection_proxy.rb +1131 -0
  25. data/lib/active_record/associations/foreign_association.rb +13 -0
  26. data/lib/active_record/associations/has_many_association.rb +144 -0
  27. data/lib/active_record/associations/has_many_through_association.rb +227 -0
  28. data/lib/active_record/associations/has_one_association.rb +120 -0
  29. data/lib/active_record/associations/has_one_through_association.rb +45 -0
  30. data/lib/active_record/associations/join_dependency.rb +262 -0
  31. data/lib/active_record/associations/join_dependency/join_association.rb +60 -0
  32. data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
  33. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  34. data/lib/active_record/associations/preloader.rb +193 -0
  35. data/lib/active_record/associations/preloader/association.rb +131 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +107 -0
  37. data/lib/active_record/associations/singular_association.rb +73 -0
  38. data/lib/active_record/associations/through_association.rb +121 -0
  39. data/lib/active_record/attribute_assignment.rb +88 -0
  40. data/lib/active_record/attribute_decorators.rb +90 -0
  41. data/lib/active_record/attribute_methods.rb +492 -0
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +78 -0
  43. data/lib/active_record/attribute_methods/dirty.rb +150 -0
  44. data/lib/active_record/attribute_methods/primary_key.rb +143 -0
  45. data/lib/active_record/attribute_methods/query.rb +42 -0
  46. data/lib/active_record/attribute_methods/read.rb +85 -0
  47. data/lib/active_record/attribute_methods/serialization.rb +90 -0
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +91 -0
  49. data/lib/active_record/attribute_methods/write.rb +68 -0
  50. data/lib/active_record/attributes.rb +266 -0
  51. data/lib/active_record/autosave_association.rb +498 -0
  52. data/lib/active_record/base.rb +329 -0
  53. data/lib/active_record/callbacks.rb +353 -0
  54. data/lib/active_record/coders/json.rb +15 -0
  55. data/lib/active_record/coders/yaml_column.rb +50 -0
  56. data/lib/active_record/collection_cache_key.rb +53 -0
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1068 -0
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +72 -0
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +540 -0
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +145 -0
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +200 -0
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +146 -0
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +685 -0
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +95 -0
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1396 -0
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +283 -0
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +628 -0
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +887 -0
  70. data/lib/active_record/connection_adapters/column.rb +91 -0
  71. data/lib/active_record/connection_adapters/connection_specification.rb +287 -0
  72. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
  73. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  74. data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
  75. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  76. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
  80. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
  81. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
  82. data/lib/active_record/connection_adapters/mysql2_adapter.rb +129 -0
  83. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -0
  84. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +163 -0
  85. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +56 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +111 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  109. data/lib/active_record/connection_adapters/postgresql/quoting.rb +168 -0
  110. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +206 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  114. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +774 -0
  115. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
  116. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  117. data/lib/active_record/connection_adapters/postgresql_adapter.rb +863 -0
  118. data/lib/active_record/connection_adapters/schema_cache.rb +118 -0
  119. data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +573 -0
  127. data/lib/active_record/connection_adapters/statement_pool.rb +61 -0
  128. data/lib/active_record/connection_handling.rb +145 -0
  129. data/lib/active_record/core.rb +559 -0
  130. data/lib/active_record/counter_cache.rb +218 -0
  131. data/lib/active_record/define_callbacks.rb +22 -0
  132. data/lib/active_record/dynamic_matchers.rb +122 -0
  133. data/lib/active_record/enum.rb +244 -0
  134. data/lib/active_record/errors.rb +380 -0
  135. data/lib/active_record/explain.rb +50 -0
  136. data/lib/active_record/explain_registry.rb +32 -0
  137. data/lib/active_record/explain_subscriber.rb +34 -0
  138. data/lib/active_record/fixture_set/file.rb +82 -0
  139. data/lib/active_record/fixtures.rb +1065 -0
  140. data/lib/active_record/gem_version.rb +17 -0
  141. data/lib/active_record/inheritance.rb +283 -0
  142. data/lib/active_record/integration.rb +155 -0
  143. data/lib/active_record/internal_metadata.rb +45 -0
  144. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  145. data/lib/active_record/locale/en.yml +48 -0
  146. data/lib/active_record/locking/optimistic.rb +198 -0
  147. data/lib/active_record/locking/pessimistic.rb +89 -0
  148. data/lib/active_record/log_subscriber.rb +137 -0
  149. data/lib/active_record/migration.rb +1378 -0
  150. data/lib/active_record/migration/command_recorder.rb +240 -0
  151. data/lib/active_record/migration/compatibility.rb +217 -0
  152. data/lib/active_record/migration/join_table.rb +17 -0
  153. data/lib/active_record/model_schema.rb +521 -0
  154. data/lib/active_record/nested_attributes.rb +600 -0
  155. data/lib/active_record/no_touching.rb +58 -0
  156. data/lib/active_record/null_relation.rb +68 -0
  157. data/lib/active_record/persistence.rb +763 -0
  158. data/lib/active_record/query_cache.rb +45 -0
  159. data/lib/active_record/querying.rb +70 -0
  160. data/lib/active_record/railtie.rb +226 -0
  161. data/lib/active_record/railties/console_sandbox.rb +7 -0
  162. data/lib/active_record/railties/controller_runtime.rb +56 -0
  163. data/lib/active_record/railties/databases.rake +377 -0
  164. data/lib/active_record/readonly_attributes.rb +24 -0
  165. data/lib/active_record/reflection.rb +1044 -0
  166. data/lib/active_record/relation.rb +629 -0
  167. data/lib/active_record/relation/batches.rb +287 -0
  168. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  169. data/lib/active_record/relation/calculations.rb +417 -0
  170. data/lib/active_record/relation/delegation.rb +147 -0
  171. data/lib/active_record/relation/finder_methods.rb +565 -0
  172. data/lib/active_record/relation/from_clause.rb +26 -0
  173. data/lib/active_record/relation/merger.rb +193 -0
  174. data/lib/active_record/relation/predicate_builder.rb +152 -0
  175. data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
  176. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  177. data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
  178. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
  179. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  180. data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
  181. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  182. data/lib/active_record/relation/query_attribute.rb +45 -0
  183. data/lib/active_record/relation/query_methods.rb +1231 -0
  184. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  185. data/lib/active_record/relation/spawn_methods.rb +77 -0
  186. data/lib/active_record/relation/where_clause.rb +186 -0
  187. data/lib/active_record/relation/where_clause_factory.rb +34 -0
  188. data/lib/active_record/result.rb +149 -0
  189. data/lib/active_record/runtime_registry.rb +24 -0
  190. data/lib/active_record/sanitization.rb +222 -0
  191. data/lib/active_record/schema.rb +70 -0
  192. data/lib/active_record/schema_dumper.rb +255 -0
  193. data/lib/active_record/schema_migration.rb +56 -0
  194. data/lib/active_record/scoping.rb +106 -0
  195. data/lib/active_record/scoping/default.rb +152 -0
  196. data/lib/active_record/scoping/named.rb +213 -0
  197. data/lib/active_record/secure_token.rb +40 -0
  198. data/lib/active_record/serialization.rb +22 -0
  199. data/lib/active_record/statement_cache.rb +121 -0
  200. data/lib/active_record/store.rb +211 -0
  201. data/lib/active_record/suppressor.rb +61 -0
  202. data/lib/active_record/table_metadata.rb +82 -0
  203. data/lib/active_record/tasks/database_tasks.rb +337 -0
  204. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  205. data/lib/active_record/tasks/postgresql_database_tasks.rb +143 -0
  206. data/lib/active_record/tasks/sqlite_database_tasks.rb +83 -0
  207. data/lib/active_record/timestamp.rb +153 -0
  208. data/lib/active_record/touch_later.rb +64 -0
  209. data/lib/active_record/transactions.rb +502 -0
  210. data/lib/active_record/translation.rb +24 -0
  211. data/lib/active_record/type.rb +79 -0
  212. data/lib/active_record/type/adapter_specific_registry.rb +136 -0
  213. data/lib/active_record/type/date.rb +9 -0
  214. data/lib/active_record/type/date_time.rb +9 -0
  215. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  216. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  217. data/lib/active_record/type/internal/timezone.rb +17 -0
  218. data/lib/active_record/type/json.rb +30 -0
  219. data/lib/active_record/type/serialized.rb +71 -0
  220. data/lib/active_record/type/text.rb +11 -0
  221. data/lib/active_record/type/time.rb +21 -0
  222. data/lib/active_record/type/type_map.rb +62 -0
  223. data/lib/active_record/type/unsigned_integer.rb +17 -0
  224. data/lib/active_record/type_caster.rb +9 -0
  225. data/lib/active_record/type_caster/connection.rb +33 -0
  226. data/lib/active_record/type_caster/map.rb +23 -0
  227. data/lib/active_record/validations.rb +93 -0
  228. data/lib/active_record/validations/absence.rb +25 -0
  229. data/lib/active_record/validations/associated.rb +60 -0
  230. data/lib/active_record/validations/length.rb +26 -0
  231. data/lib/active_record/validations/presence.rb +68 -0
  232. data/lib/active_record/validations/uniqueness.rb +238 -0
  233. data/lib/active_record/version.rb +10 -0
  234. data/lib/rails/generators/active_record.rb +19 -0
  235. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  236. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  237. data/lib/rails/generators/active_record/migration.rb +35 -0
  238. data/lib/rails/generators/active_record/migration/migration_generator.rb +78 -0
  239. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  240. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +46 -0
  241. data/lib/rails/generators/active_record/model/model_generator.rb +48 -0
  242. data/lib/rails/generators/active_record/model/templates/model.rb.tt +13 -0
  243. data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
  244. metadata +333 -0
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ # = Active Record Query Cache
5
+ class QueryCache
6
+ module ClassMethods
7
+ # Enable the query cache within the block if Active Record is configured.
8
+ # If it's not, it will execute the given block.
9
+ def cache(&block)
10
+ if connected? || !configurations.empty?
11
+ connection.cache(&block)
12
+ else
13
+ yield
14
+ end
15
+ end
16
+
17
+ # Disable the query cache within the block if Active Record is configured.
18
+ # If it's not, it will execute the given block.
19
+ def uncached(&block)
20
+ if connected? || !configurations.empty?
21
+ connection.uncached(&block)
22
+ else
23
+ yield
24
+ end
25
+ end
26
+ end
27
+
28
+ def self.run
29
+ ActiveRecord::Base.connection_handler.connection_pool_list.
30
+ reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! }
31
+ end
32
+
33
+ def self.complete(pools)
34
+ pools.each { |pool| pool.disable_query_cache! }
35
+
36
+ ActiveRecord::Base.connection_handler.connection_pool_list.each do |pool|
37
+ pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
38
+ end
39
+ end
40
+
41
+ def self.install_executor_hooks(executor = ActiveSupport::Executor)
42
+ executor.register_hook(self)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Querying
5
+ delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, :none?, :one?, to: :all
6
+ delegate :second, :second!, :third, :third!, :fourth, :fourth!, :fifth, :fifth!, :forty_two, :forty_two!, :third_to_last, :third_to_last!, :second_to_last, :second_to_last!, to: :all
7
+ delegate :first_or_create, :first_or_create!, :first_or_initialize, to: :all
8
+ delegate :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, to: :all
9
+ delegate :find_by, :find_by!, to: :all
10
+ delegate :destroy_all, :delete_all, :update_all, to: :all
11
+ delegate :find_each, :find_in_batches, :in_batches, to: :all
12
+ delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :left_joins, :left_outer_joins, :or,
13
+ :where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly, :extending,
14
+ :having, :create_with, :distinct, :references, :none, :unscope, :merge, to: :all
15
+ delegate :count, :average, :minimum, :maximum, :sum, :calculate, to: :all
16
+ delegate :pluck, :ids, to: :all
17
+
18
+ # Executes a custom SQL query against your database and returns all the results. The results will
19
+ # be returned as an array with columns requested encapsulated as attributes of the model you call
20
+ # this method from. If you call <tt>Product.find_by_sql</tt> then the results will be returned in
21
+ # a +Product+ object with the attributes you specified in the SQL query.
22
+ #
23
+ # If you call a complicated SQL query which spans multiple tables the columns specified by the
24
+ # SELECT will be attributes of the model, whether or not they are columns of the corresponding
25
+ # table.
26
+ #
27
+ # The +sql+ parameter is a full SQL query as a string. It will be called as is, there will be
28
+ # no database agnostic conversions performed. This should be a last resort because using, for example,
29
+ # MySQL specific terms will lock you to using that particular database engine or require you to
30
+ # change your call if you switch engines.
31
+ #
32
+ # # A simple SQL query spanning multiple tables
33
+ # Post.find_by_sql "SELECT p.title, c.author FROM posts p, comments c WHERE p.id = c.post_id"
34
+ # # => [#<Post:0x36bff9c @attributes={"title"=>"Ruby Meetup", "first_name"=>"Quentin"}>, ...]
35
+ #
36
+ # You can use the same string replacement techniques as you can with <tt>ActiveRecord::QueryMethods#where</tt>:
37
+ #
38
+ # Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
39
+ # Post.find_by_sql ["SELECT body FROM comments WHERE author = :user_id OR approved_by = :user_id", { :user_id => user_id }]
40
+ def find_by_sql(sql, binds = [], preparable: nil, &block)
41
+ result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds, preparable: preparable)
42
+ column_types = result_set.column_types.dup
43
+ attribute_types.each_key { |k| column_types.delete k }
44
+ message_bus = ActiveSupport::Notifications.instrumenter
45
+
46
+ payload = {
47
+ record_count: result_set.length,
48
+ class_name: name
49
+ }
50
+
51
+ message_bus.instrument("instantiation.active_record", payload) do
52
+ result_set.map { |record| instantiate(record, column_types, &block) }
53
+ end
54
+ end
55
+
56
+ # Returns the result of an SQL statement that should only include a COUNT(*) in the SELECT part.
57
+ # The use of this method should be restricted to complicated SQL queries that can't be executed
58
+ # using the ActiveRecord::Calculations class methods. Look into those before using this.
59
+ #
60
+ # Product.count_by_sql "SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id"
61
+ # # => 12
62
+ #
63
+ # ==== Parameters
64
+ #
65
+ # * +sql+ - An SQL statement which should return a count query from the database, see the example above.
66
+ def count_by_sql(sql)
67
+ connection.select_value(sanitize_sql(sql), "#{name} Count").to_i
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,226 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record"
4
+ require "rails"
5
+ require "active_model/railtie"
6
+
7
+ # For now, action_controller must always be present with
8
+ # Rails, so let's make sure that it gets required before
9
+ # here. This is needed for correctly setting up the middleware.
10
+ # In the future, this might become an optional require.
11
+ require "action_controller/railtie"
12
+
13
+ module ActiveRecord
14
+ # = Active Record Railtie
15
+ class Railtie < Rails::Railtie # :nodoc:
16
+ config.active_record = ActiveSupport::OrderedOptions.new
17
+
18
+ config.app_generators.orm :active_record, migration: true,
19
+ timestamps: true
20
+
21
+ config.action_dispatch.rescue_responses.merge!(
22
+ "ActiveRecord::RecordNotFound" => :not_found,
23
+ "ActiveRecord::StaleObjectError" => :conflict,
24
+ "ActiveRecord::RecordInvalid" => :unprocessable_entity,
25
+ "ActiveRecord::RecordNotSaved" => :unprocessable_entity
26
+ )
27
+
28
+ config.active_record.use_schema_cache_dump = true
29
+ config.active_record.maintain_test_schema = true
30
+
31
+ config.active_record.sqlite3 = ActiveSupport::OrderedOptions.new
32
+ config.active_record.sqlite3.represent_boolean_as_integer = nil
33
+
34
+ config.eager_load_namespaces << ActiveRecord
35
+
36
+ rake_tasks do
37
+ namespace :db do
38
+ task :load_config do
39
+ ActiveRecord::Tasks::DatabaseTasks.database_configuration = Rails.application.config.database_configuration
40
+
41
+ if defined?(ENGINE_ROOT) && engine = Rails::Engine.find(ENGINE_ROOT)
42
+ if engine.paths["db/migrate"].existent
43
+ ActiveRecord::Tasks::DatabaseTasks.migrations_paths += engine.paths["db/migrate"].to_a
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ load "active_record/railties/databases.rake"
50
+ end
51
+
52
+ # When loading console, force ActiveRecord::Base to be loaded
53
+ # to avoid cross references when loading a constant for the
54
+ # first time. Also, make it output to STDERR.
55
+ console do |app|
56
+ require "active_record/railties/console_sandbox" if app.sandbox?
57
+ require "active_record/base"
58
+ unless ActiveSupport::Logger.logger_outputs_to?(Rails.logger, STDERR, STDOUT)
59
+ console = ActiveSupport::Logger.new(STDERR)
60
+ Rails.logger.extend ActiveSupport::Logger.broadcast console
61
+ end
62
+ ActiveRecord::Base.verbose_query_logs = false
63
+ end
64
+
65
+ runner do
66
+ require "active_record/base"
67
+ end
68
+
69
+ initializer "active_record.initialize_timezone" do
70
+ ActiveSupport.on_load(:active_record) do
71
+ self.time_zone_aware_attributes = true
72
+ self.default_timezone = :utc
73
+ end
74
+ end
75
+
76
+ initializer "active_record.logger" do
77
+ ActiveSupport.on_load(:active_record) { self.logger ||= ::Rails.logger }
78
+ end
79
+
80
+ initializer "active_record.migration_error" do
81
+ if config.active_record.delete(:migration_error) == :page_load
82
+ config.app_middleware.insert_after ::ActionDispatch::Callbacks,
83
+ ActiveRecord::Migration::CheckPending
84
+ end
85
+ end
86
+
87
+ initializer "active_record.check_schema_cache_dump" do
88
+ if config.active_record.delete(:use_schema_cache_dump)
89
+ config.after_initialize do |app|
90
+ ActiveSupport.on_load(:active_record) do
91
+ filename = File.join(app.config.paths["db"].first, "schema_cache.yml")
92
+
93
+ if File.file?(filename)
94
+ current_version = ActiveRecord::Migrator.current_version
95
+
96
+ next if current_version.nil?
97
+
98
+ cache = YAML.load(File.read(filename))
99
+ if cache.version == current_version
100
+ connection.schema_cache = cache
101
+ connection_pool.schema_cache = cache.dup
102
+ else
103
+ warn "Ignoring db/schema_cache.yml because it has expired. The current schema version is #{current_version}, but the one in the cache is #{cache.version}."
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+ initializer "active_record.warn_on_records_fetched_greater_than" do
112
+ if config.active_record.warn_on_records_fetched_greater_than
113
+ ActiveSupport.on_load(:active_record) do
114
+ require "active_record/relation/record_fetch_warning"
115
+ end
116
+ end
117
+ end
118
+
119
+ initializer "active_record.set_configs" do |app|
120
+ ActiveSupport.on_load(:active_record) do
121
+ configs = app.config.active_record.dup
122
+ configs.delete(:sqlite3)
123
+ configs.each do |k, v|
124
+ send "#{k}=", v
125
+ end
126
+ end
127
+ end
128
+
129
+ # This sets the database configuration from Configuration#database_configuration
130
+ # and then establishes the connection.
131
+ initializer "active_record.initialize_database" do
132
+ ActiveSupport.on_load(:active_record) do
133
+ self.configurations = Rails.application.config.database_configuration
134
+
135
+ begin
136
+ establish_connection
137
+ rescue ActiveRecord::NoDatabaseError
138
+ warn <<-end_warning
139
+ Oops - You have a database configured, but it doesn't exist yet!
140
+
141
+ Here's how to get started:
142
+
143
+ 1. Configure your database in config/database.yml.
144
+ 2. Run `bin/rails db:create` to create the database.
145
+ 3. Run `bin/rails db:setup` to load your database schema.
146
+ end_warning
147
+ raise
148
+ end
149
+ end
150
+ end
151
+
152
+ # Expose database runtime to controller for logging.
153
+ initializer "active_record.log_runtime" do
154
+ require "active_record/railties/controller_runtime"
155
+ ActiveSupport.on_load(:action_controller) do
156
+ include ActiveRecord::Railties::ControllerRuntime
157
+ end
158
+ end
159
+
160
+ initializer "active_record.set_reloader_hooks" do
161
+ ActiveSupport.on_load(:active_record) do
162
+ ActiveSupport::Reloader.before_class_unload do
163
+ if ActiveRecord::Base.connected?
164
+ ActiveRecord::Base.clear_cache!
165
+ ActiveRecord::Base.clear_reloadable_connections!
166
+ end
167
+ end
168
+ end
169
+ end
170
+
171
+ initializer "active_record.set_executor_hooks" do
172
+ ActiveRecord::QueryCache.install_executor_hooks
173
+ end
174
+
175
+ initializer "active_record.add_watchable_files" do |app|
176
+ path = app.paths["db"].first
177
+ config.watchable_files.concat ["#{path}/schema.rb", "#{path}/structure.sql"]
178
+ end
179
+
180
+ initializer "active_record.clear_active_connections" do
181
+ config.after_initialize do
182
+ ActiveSupport.on_load(:active_record) do
183
+ # Ideally the application doesn't connect to the database during boot,
184
+ # but sometimes it does. In case it did, we want to empty out the
185
+ # connection pools so that a non-database-using process (e.g. a master
186
+ # process in a forking server model) doesn't retain a needless
187
+ # connection. If it was needed, the incremental cost of reestablishing
188
+ # this connection is trivial: the rest of the pool would need to be
189
+ # populated anyway.
190
+
191
+ clear_active_connections!
192
+ flush_idle_connections!
193
+ end
194
+ end
195
+ end
196
+
197
+ initializer "active_record.check_represent_sqlite3_boolean_as_integer" do
198
+ config.after_initialize do
199
+ ActiveSupport.on_load(:active_record_sqlite3adapter) do
200
+ represent_boolean_as_integer = Rails.application.config.active_record.sqlite3.delete(:represent_boolean_as_integer)
201
+ unless represent_boolean_as_integer.nil?
202
+ ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = represent_boolean_as_integer
203
+ end
204
+
205
+ unless ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
206
+ ActiveSupport::Deprecation.warn <<-MSG
207
+ Leaving `ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer`
208
+ set to false is deprecated. SQLite databases have used 't' and 'f' to serialize
209
+ boolean values and must have old data converted to 1 and 0 (its native boolean
210
+ serialization) before setting this flag to true. Conversion can be accomplished
211
+ by setting up a rake task which runs
212
+
213
+ ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 1)
214
+ ExampleModel.where("boolean_column = 'f'").update_all(boolean_column: 0)
215
+
216
+ for all models and all boolean columns, after which the flag must be set to
217
+ true by adding the following to your application.rb file:
218
+
219
+ Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
220
+ MSG
221
+ end
222
+ end
223
+ end
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ ActiveRecord::Base.connection.begin_transaction(joinable: false)
4
+
5
+ at_exit do
6
+ ActiveRecord::Base.connection.rollback_transaction
7
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/attr_internal"
4
+ require "active_record/log_subscriber"
5
+
6
+ module ActiveRecord
7
+ module Railties # :nodoc:
8
+ module ControllerRuntime #:nodoc:
9
+ extend ActiveSupport::Concern
10
+
11
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
12
+ # Workaround for Ruby 2.2 "private attribute?" warning.
13
+ protected
14
+
15
+ attr_internal :db_runtime
16
+
17
+ private
18
+
19
+ def process_action(action, *args)
20
+ # We also need to reset the runtime before each action
21
+ # because of queries in middleware or in cases we are streaming
22
+ # and it won't be cleaned up by the method below.
23
+ ActiveRecord::LogSubscriber.reset_runtime
24
+ super
25
+ end
26
+
27
+ def cleanup_view_runtime
28
+ if logger && logger.info? && ActiveRecord::Base.connected?
29
+ db_rt_before_render = ActiveRecord::LogSubscriber.reset_runtime
30
+ self.db_runtime = (db_runtime || 0) + db_rt_before_render
31
+ runtime = super
32
+ db_rt_after_render = ActiveRecord::LogSubscriber.reset_runtime
33
+ self.db_runtime += db_rt_after_render
34
+ runtime - db_rt_after_render
35
+ else
36
+ super
37
+ end
38
+ end
39
+
40
+ def append_info_to_payload(payload)
41
+ super
42
+ if ActiveRecord::Base.connected?
43
+ payload[:db_runtime] = (db_runtime || 0) + ActiveRecord::LogSubscriber.reset_runtime
44
+ end
45
+ end
46
+
47
+ module ClassMethods # :nodoc:
48
+ def log_process_action(payload)
49
+ messages, db_runtime = super, payload[:db_runtime]
50
+ messages << ("ActiveRecord: %.1fms" % db_runtime.to_f) if db_runtime
51
+ messages
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,377 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record"
4
+
5
+ db_namespace = namespace :db do
6
+ desc "Set the environment value for the database"
7
+ task "environment:set" => :load_config do
8
+ ActiveRecord::InternalMetadata.create_table
9
+ ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.migration_context.current_environment
10
+ end
11
+
12
+ task check_protected_environments: :load_config do
13
+ ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
14
+ end
15
+
16
+ task load_config: :environment do
17
+ ActiveRecord::Base.configurations = ActiveRecord::Tasks::DatabaseTasks.database_configuration || {}
18
+ ActiveRecord::Migrator.migrations_paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
19
+ end
20
+
21
+ namespace :create do
22
+ task all: :load_config do
23
+ ActiveRecord::Tasks::DatabaseTasks.create_all
24
+ end
25
+ end
26
+
27
+ desc "Creates the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:create:all to create all databases in the config). Without RAILS_ENV or when RAILS_ENV is development, it defaults to creating the development and test databases."
28
+ task create: [:load_config] do
29
+ ActiveRecord::Tasks::DatabaseTasks.create_current
30
+ end
31
+
32
+ namespace :drop do
33
+ task all: [:load_config, :check_protected_environments] do
34
+ ActiveRecord::Tasks::DatabaseTasks.drop_all
35
+ end
36
+ end
37
+
38
+ desc "Drops the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all databases in the config). Without RAILS_ENV or when RAILS_ENV is development, it defaults to dropping the development and test databases."
39
+ task drop: [:load_config, :check_protected_environments] do
40
+ db_namespace["drop:_unsafe"].invoke
41
+ end
42
+
43
+ task "drop:_unsafe" => [:load_config] do
44
+ ActiveRecord::Tasks::DatabaseTasks.drop_current
45
+ end
46
+
47
+ namespace :purge do
48
+ task all: [:load_config, :check_protected_environments] do
49
+ ActiveRecord::Tasks::DatabaseTasks.purge_all
50
+ end
51
+ end
52
+
53
+ # desc "Empty the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:purge:all to purge all databases in the config). Without RAILS_ENV it defaults to purging the development and test databases."
54
+ task purge: [:load_config, :check_protected_environments] do
55
+ ActiveRecord::Tasks::DatabaseTasks.purge_current
56
+ end
57
+
58
+ desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
59
+ task migrate: :load_config do
60
+ ActiveRecord::Tasks::DatabaseTasks.migrate
61
+ db_namespace["_dump"].invoke
62
+ end
63
+
64
+ # IMPORTANT: This task won't dump the schema if ActiveRecord::Base.dump_schema_after_migration is set to false
65
+ task :_dump do
66
+ if ActiveRecord::Base.dump_schema_after_migration
67
+ case ActiveRecord::Base.schema_format
68
+ when :ruby then db_namespace["schema:dump"].invoke
69
+ when :sql then db_namespace["structure:dump"].invoke
70
+ else
71
+ raise "unknown schema format #{ActiveRecord::Base.schema_format}"
72
+ end
73
+ end
74
+ # Allow this task to be called as many times as required. An example is the
75
+ # migrate:redo task, which calls other two internally that depend on this one.
76
+ db_namespace["_dump"].reenable
77
+ end
78
+
79
+ namespace :migrate do
80
+ # desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
81
+ task redo: :load_config do
82
+ raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
83
+
84
+ if ENV["VERSION"]
85
+ db_namespace["migrate:down"].invoke
86
+ db_namespace["migrate:up"].invoke
87
+ else
88
+ db_namespace["rollback"].invoke
89
+ db_namespace["migrate"].invoke
90
+ end
91
+ end
92
+
93
+ # desc 'Resets your database using your migrations for the current environment'
94
+ task reset: ["db:drop", "db:create", "db:migrate"]
95
+
96
+ # desc 'Runs the "up" for a given migration VERSION.'
97
+ task up: :load_config do
98
+ raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
99
+
100
+ ActiveRecord::Tasks::DatabaseTasks.check_target_version
101
+
102
+ ActiveRecord::Base.connection.migration_context.run(
103
+ :up,
104
+ ActiveRecord::Tasks::DatabaseTasks.target_version
105
+ )
106
+ db_namespace["_dump"].invoke
107
+ end
108
+
109
+ # desc 'Runs the "down" for a given migration VERSION.'
110
+ task down: :load_config do
111
+ raise "VERSION is required - To go down one migration, use db:rollback" if !ENV["VERSION"] || ENV["VERSION"].empty?
112
+
113
+ ActiveRecord::Tasks::DatabaseTasks.check_target_version
114
+
115
+ ActiveRecord::Base.connection.migration_context.run(
116
+ :down,
117
+ ActiveRecord::Tasks::DatabaseTasks.target_version
118
+ )
119
+ db_namespace["_dump"].invoke
120
+ end
121
+
122
+ desc "Display status of migrations"
123
+ task status: :load_config do
124
+ unless ActiveRecord::SchemaMigration.table_exists?
125
+ abort "Schema migrations table does not exist yet."
126
+ end
127
+
128
+ # output
129
+ puts "\ndatabase: #{ActiveRecord::Base.connection_config[:database]}\n\n"
130
+ puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
131
+ puts "-" * 50
132
+ ActiveRecord::Base.connection.migration_context.migrations_status.each do |status, version, name|
133
+ puts "#{status.center(8)} #{version.ljust(14)} #{name}"
134
+ end
135
+ puts
136
+ end
137
+ end
138
+
139
+ desc "Rolls the schema back to the previous version (specify steps w/ STEP=n)."
140
+ task rollback: :load_config do
141
+ step = ENV["STEP"] ? ENV["STEP"].to_i : 1
142
+ ActiveRecord::Base.connection.migration_context.rollback(step)
143
+ db_namespace["_dump"].invoke
144
+ end
145
+
146
+ # desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
147
+ task forward: :load_config do
148
+ step = ENV["STEP"] ? ENV["STEP"].to_i : 1
149
+ ActiveRecord::Base.connection.migration_context.forward(step)
150
+ db_namespace["_dump"].invoke
151
+ end
152
+
153
+ # desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.'
154
+ task reset: [ "db:drop", "db:setup" ]
155
+
156
+ # desc "Retrieves the charset for the current environment's database"
157
+ task charset: :load_config do
158
+ puts ActiveRecord::Tasks::DatabaseTasks.charset_current
159
+ end
160
+
161
+ # desc "Retrieves the collation for the current environment's database"
162
+ task collation: :load_config do
163
+ begin
164
+ puts ActiveRecord::Tasks::DatabaseTasks.collation_current
165
+ rescue NoMethodError
166
+ $stderr.puts "Sorry, your database adapter is not supported yet. Feel free to submit a patch."
167
+ end
168
+ end
169
+
170
+ desc "Retrieves the current schema version number"
171
+ task version: :load_config do
172
+ puts "Current version: #{ActiveRecord::Base.connection.migration_context.current_version}"
173
+ end
174
+
175
+ # desc "Raises an error if there are pending migrations"
176
+ task abort_if_pending_migrations: :load_config do
177
+ pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
178
+
179
+ if pending_migrations.any?
180
+ puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
181
+ pending_migrations.each do |pending_migration|
182
+ puts " %4d %s" % [pending_migration.version, pending_migration.name]
183
+ end
184
+ abort %{Run `rails db:migrate` to update your database then try again.}
185
+ end
186
+ end
187
+
188
+ desc "Creates the database, loads the schema, and initializes with the seed data (use db:reset to also drop the database first)"
189
+ task setup: ["db:schema:load_if_ruby", "db:structure:load_if_sql", :seed]
190
+
191
+ desc "Loads the seed data from db/seeds.rb"
192
+ task :seed do
193
+ db_namespace["abort_if_pending_migrations"].invoke
194
+ ActiveRecord::Tasks::DatabaseTasks.load_seed
195
+ end
196
+
197
+ namespace :fixtures do
198
+ desc "Loads fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
199
+ task load: :load_config do
200
+ require "active_record/fixtures"
201
+
202
+ base_dir = ActiveRecord::Tasks::DatabaseTasks.fixtures_path
203
+
204
+ fixtures_dir = if ENV["FIXTURES_DIR"]
205
+ File.join base_dir, ENV["FIXTURES_DIR"]
206
+ else
207
+ base_dir
208
+ end
209
+
210
+ fixture_files = if ENV["FIXTURES"]
211
+ ENV["FIXTURES"].split(",")
212
+ else
213
+ # The use of String#[] here is to support namespaced fixtures.
214
+ Dir["#{fixtures_dir}/**/*.yml"].map { |f| f[(fixtures_dir.size + 1)..-5] }
215
+ end
216
+
217
+ ActiveRecord::FixtureSet.create_fixtures(fixtures_dir, fixture_files)
218
+ end
219
+
220
+ # desc "Search for a fixture given a LABEL or ID. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
221
+ task identify: :load_config do
222
+ require "active_record/fixtures"
223
+
224
+ label, id = ENV["LABEL"], ENV["ID"]
225
+ raise "LABEL or ID required" if label.blank? && id.blank?
226
+
227
+ puts %Q(The fixture ID for "#{label}" is #{ActiveRecord::FixtureSet.identify(label)}.) if label
228
+
229
+ base_dir = ActiveRecord::Tasks::DatabaseTasks.fixtures_path
230
+
231
+ Dir["#{base_dir}/**/*.yml"].each do |file|
232
+ if data = YAML.load(ERB.new(IO.read(file)).result)
233
+ data.each_key do |key|
234
+ key_id = ActiveRecord::FixtureSet.identify(key)
235
+
236
+ if key == label || key_id == id.to_i
237
+ puts "#{file}: #{key} (#{key_id})"
238
+ end
239
+ end
240
+ end
241
+ end
242
+ end
243
+ end
244
+
245
+ namespace :schema do
246
+ desc "Creates a db/schema.rb file that is portable against any DB supported by Active Record"
247
+ task dump: :load_config do
248
+ require "active_record/schema_dumper"
249
+ filename = ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema.rb")
250
+ File.open(filename, "w:utf-8") do |file|
251
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
252
+ end
253
+ db_namespace["schema:dump"].reenable
254
+ end
255
+
256
+ desc "Loads a schema.rb file into the database"
257
+ task load: [:load_config, :check_protected_environments] do
258
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:ruby, ENV["SCHEMA"])
259
+ end
260
+
261
+ task load_if_ruby: ["db:create", :environment] do
262
+ db_namespace["schema:load"].invoke if ActiveRecord::Base.schema_format == :ruby
263
+ end
264
+
265
+ namespace :cache do
266
+ desc "Creates a db/schema_cache.yml file."
267
+ task dump: :load_config do
268
+ conn = ActiveRecord::Base.connection
269
+ filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.yml")
270
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(conn, filename)
271
+ end
272
+
273
+ desc "Clears a db/schema_cache.yml file."
274
+ task clear: :load_config do
275
+ filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.yml")
276
+ rm_f filename, verbose: false
277
+ end
278
+ end
279
+
280
+ end
281
+
282
+ namespace :structure do
283
+ desc "Dumps the database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
284
+ task dump: :load_config do
285
+ filename = ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql")
286
+ current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
287
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(current_config, filename)
288
+
289
+ if ActiveRecord::SchemaMigration.table_exists?
290
+ File.open(filename, "a") do |f|
291
+ f.puts ActiveRecord::Base.connection.dump_schema_information
292
+ f.print "\n"
293
+ end
294
+ end
295
+ db_namespace["structure:dump"].reenable
296
+ end
297
+
298
+ desc "Recreates the databases from the structure.sql file"
299
+ task load: [:load_config, :check_protected_environments] do
300
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:sql, ENV["SCHEMA"])
301
+ end
302
+
303
+ task load_if_sql: ["db:create", :environment] do
304
+ db_namespace["structure:load"].invoke if ActiveRecord::Base.schema_format == :sql
305
+ end
306
+ end
307
+
308
+ namespace :test do
309
+ # desc "Recreate the test database from the current schema"
310
+ task load: %w(db:test:purge) do
311
+ case ActiveRecord::Base.schema_format
312
+ when :ruby
313
+ db_namespace["test:load_schema"].invoke
314
+ when :sql
315
+ db_namespace["test:load_structure"].invoke
316
+ end
317
+ end
318
+
319
+ # desc "Recreate the test database from an existent schema.rb file"
320
+ task load_schema: %w(db:test:purge) do
321
+ begin
322
+ should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
323
+ ActiveRecord::Schema.verbose = false
324
+ ActiveRecord::Tasks::DatabaseTasks.load_schema ActiveRecord::Base.configurations["test"], :ruby, ENV["SCHEMA"], "test"
325
+ ensure
326
+ if should_reconnect
327
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[ActiveRecord::Tasks::DatabaseTasks.env])
328
+ end
329
+ end
330
+ end
331
+
332
+ # desc "Recreate the test database from an existent structure.sql file"
333
+ task load_structure: %w(db:test:purge) do
334
+ ActiveRecord::Tasks::DatabaseTasks.load_schema ActiveRecord::Base.configurations["test"], :sql, ENV["SCHEMA"], "test"
335
+ end
336
+
337
+ # desc "Empty the test database"
338
+ task purge: %w(load_config check_protected_environments) do
339
+ ActiveRecord::Tasks::DatabaseTasks.purge ActiveRecord::Base.configurations["test"]
340
+ end
341
+
342
+ # desc 'Load the test schema'
343
+ task prepare: :load_config do
344
+ unless ActiveRecord::Base.configurations.blank?
345
+ db_namespace["test:load"].invoke
346
+ end
347
+ end
348
+ end
349
+ end
350
+
351
+ namespace :railties do
352
+ namespace :install do
353
+ # desc "Copies missing migrations from Railties (e.g. engines). You can specify Railties to use with FROM=railtie1,railtie2"
354
+ task migrations: :'db:load_config' do
355
+ to_load = ENV["FROM"].blank? ? :all : ENV["FROM"].split(",").map(&:strip)
356
+ railties = {}
357
+ Rails.application.migration_railties.each do |railtie|
358
+ next unless to_load == :all || to_load.include?(railtie.railtie_name)
359
+
360
+ if railtie.respond_to?(:paths) && (path = railtie.paths["db/migrate"].first)
361
+ railties[railtie.railtie_name] = path
362
+ end
363
+ end
364
+
365
+ on_skip = Proc.new do |name, migration|
366
+ puts "NOTE: Migration #{migration.basename} from #{name} has been skipped. Migration with the same name already exists."
367
+ end
368
+
369
+ on_copy = Proc.new do |name, migration|
370
+ puts "Copied migration #{migration.basename} from #{name}"
371
+ end
372
+
373
+ ActiveRecord::Migration.copy(ActiveRecord::Tasks::DatabaseTasks.migrations_paths.first, railties,
374
+ on_skip: on_skip, on_copy: on_copy)
375
+ end
376
+ end
377
+ end