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,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class TableMetadata # :nodoc:
5
+ delegate :foreign_type, :foreign_key, :join_primary_key, :join_foreign_key, to: :association, prefix: true
6
+
7
+ def initialize(klass, arel_table, association = nil)
8
+ @klass = klass
9
+ @arel_table = arel_table
10
+ @association = association
11
+ end
12
+
13
+ def resolve_column_aliases(hash)
14
+ new_hash = hash.dup
15
+ hash.each do |key, _|
16
+ if (key.is_a?(Symbol)) && klass.attribute_alias?(key)
17
+ new_hash[klass.attribute_alias(key)] = new_hash.delete(key)
18
+ end
19
+ end
20
+ new_hash
21
+ end
22
+
23
+ def arel_attribute(column_name)
24
+ if klass
25
+ klass.arel_attribute(column_name, arel_table)
26
+ else
27
+ arel_table[column_name]
28
+ end
29
+ end
30
+
31
+ def type(column_name)
32
+ if klass
33
+ klass.type_for_attribute(column_name)
34
+ else
35
+ Type.default_value
36
+ end
37
+ end
38
+
39
+ def has_column?(column_name)
40
+ klass && klass.columns_hash.key?(column_name.to_s)
41
+ end
42
+
43
+ def associated_with?(association_name)
44
+ klass && klass._reflect_on_association(association_name)
45
+ end
46
+
47
+ def associated_table(table_name)
48
+ association = klass._reflect_on_association(table_name) || klass._reflect_on_association(table_name.to_s.singularize)
49
+
50
+ if !association && table_name == arel_table.name
51
+ return self
52
+ elsif association && !association.polymorphic?
53
+ association_klass = association.klass
54
+ arel_table = association_klass.arel_table.alias(table_name)
55
+ else
56
+ type_caster = TypeCaster::Connection.new(klass, table_name)
57
+ association_klass = nil
58
+ arel_table = Arel::Table.new(table_name, type_caster: type_caster)
59
+ end
60
+
61
+ TableMetadata.new(association_klass, arel_table, association)
62
+ end
63
+
64
+ def polymorphic_association?
65
+ association && association.polymorphic?
66
+ end
67
+
68
+ def aggregated_with?(aggregation_name)
69
+ klass && reflect_on_aggregation(aggregation_name)
70
+ end
71
+
72
+ def reflect_on_aggregation(aggregation_name)
73
+ klass.reflect_on_aggregation(aggregation_name)
74
+ end
75
+
76
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
77
+ # Workaround for Ruby 2.2 "private attribute?" warning.
78
+ protected
79
+
80
+ attr_reader :klass, :arel_table, :association
81
+ end
82
+ end
@@ -0,0 +1,337 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Tasks # :nodoc:
5
+ class DatabaseAlreadyExists < StandardError; end # :nodoc:
6
+ class DatabaseNotSupported < StandardError; end # :nodoc:
7
+
8
+ # ActiveRecord::Tasks::DatabaseTasks is a utility class, which encapsulates
9
+ # logic behind common tasks used to manage database and migrations.
10
+ #
11
+ # The tasks defined here are used with Rake tasks provided by Active Record.
12
+ #
13
+ # In order to use DatabaseTasks, a few config values need to be set. All the needed
14
+ # config values are set by Rails already, so it's necessary to do it only if you
15
+ # want to change the defaults or when you want to use Active Record outside of Rails
16
+ # (in such case after configuring the database tasks, you can also use the rake tasks
17
+ # defined in Active Record).
18
+ #
19
+ # The possible config values are:
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.
28
+ #
29
+ # Example usage of DatabaseTasks outside Rails could look as such:
30
+ #
31
+ # include ActiveRecord::Tasks
32
+ # DatabaseTasks.database_configuration = YAML.load_file('my_database_config.yml')
33
+ # DatabaseTasks.db_dir = 'db'
34
+ # # other settings...
35
+ #
36
+ # DatabaseTasks.create_current('production')
37
+ module DatabaseTasks
38
+ ##
39
+ # :singleton-method:
40
+ # Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:structure:dump
41
+ mattr_accessor :structure_dump_flags, instance_accessor: false
42
+
43
+ ##
44
+ # :singleton-method:
45
+ # Extra flags passed to database CLI tool when calling db:structure:load
46
+ mattr_accessor :structure_load_flags, instance_accessor: false
47
+
48
+ extend self
49
+
50
+ attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
51
+ attr_accessor :database_configuration
52
+
53
+ LOCAL_HOSTS = ["127.0.0.1", "localhost"]
54
+
55
+ def check_protected_environments!
56
+ unless ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"]
57
+ current = ActiveRecord::Base.connection.migration_context.current_environment
58
+ stored = ActiveRecord::Base.connection.migration_context.last_stored_environment
59
+
60
+ if ActiveRecord::Base.connection.migration_context.protected_environment?
61
+ raise ActiveRecord::ProtectedEnvironmentError.new(stored)
62
+ end
63
+
64
+ if stored && stored != current
65
+ raise ActiveRecord::EnvironmentMismatchError.new(current: current, stored: stored)
66
+ end
67
+ end
68
+ rescue ActiveRecord::NoDatabaseError
69
+ end
70
+
71
+ def register_task(pattern, task)
72
+ @tasks ||= {}
73
+ @tasks[pattern] = task
74
+ end
75
+
76
+ register_task(/mysql/, "ActiveRecord::Tasks::MySQLDatabaseTasks")
77
+ register_task(/postgresql/, "ActiveRecord::Tasks::PostgreSQLDatabaseTasks")
78
+ register_task(/sqlite/, "ActiveRecord::Tasks::SQLiteDatabaseTasks")
79
+
80
+ def db_dir
81
+ @db_dir ||= Rails.application.config.paths["db"].first
82
+ end
83
+
84
+ def migrations_paths
85
+ @migrations_paths ||= Rails.application.paths["db/migrate"].to_a
86
+ end
87
+
88
+ def fixtures_path
89
+ @fixtures_path ||= if ENV["FIXTURES_PATH"]
90
+ File.join(root, ENV["FIXTURES_PATH"])
91
+ else
92
+ File.join(root, "test", "fixtures")
93
+ end
94
+ end
95
+
96
+ def root
97
+ @root ||= Rails.root
98
+ end
99
+
100
+ def env
101
+ @env ||= Rails.env
102
+ end
103
+
104
+ def seed_loader
105
+ @seed_loader ||= Rails.application
106
+ end
107
+
108
+ def current_config(options = {})
109
+ options.reverse_merge! env: env
110
+ if options.has_key?(:config)
111
+ @current_config = options[:config]
112
+ else
113
+ @current_config ||= ActiveRecord::Base.configurations[options[:env]]
114
+ end
115
+ end
116
+
117
+ def create(*arguments)
118
+ configuration = arguments.first
119
+ class_for_adapter(configuration["adapter"]).new(*arguments).create
120
+ $stdout.puts "Created database '#{configuration['database']}'"
121
+ rescue DatabaseAlreadyExists
122
+ $stderr.puts "Database '#{configuration['database']}' already exists"
123
+ rescue Exception => error
124
+ $stderr.puts error
125
+ $stderr.puts "Couldn't create '#{configuration['database']}' database. Please check your configuration."
126
+ raise
127
+ end
128
+
129
+ def create_all
130
+ old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name)
131
+ each_local_configuration { |configuration| create configuration }
132
+ if old_pool
133
+ ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec.to_hash)
134
+ end
135
+ end
136
+
137
+ def create_current(environment = env)
138
+ each_current_configuration(environment) { |configuration|
139
+ create configuration
140
+ }
141
+ ActiveRecord::Base.establish_connection(environment.to_sym)
142
+ end
143
+
144
+ def drop(*arguments)
145
+ configuration = arguments.first
146
+ class_for_adapter(configuration["adapter"]).new(*arguments).drop
147
+ $stdout.puts "Dropped database '#{configuration['database']}'"
148
+ rescue ActiveRecord::NoDatabaseError
149
+ $stderr.puts "Database '#{configuration['database']}' does not exist"
150
+ rescue Exception => error
151
+ $stderr.puts error
152
+ $stderr.puts "Couldn't drop database '#{configuration['database']}'"
153
+ raise
154
+ end
155
+
156
+ def drop_all
157
+ each_local_configuration { |configuration| drop configuration }
158
+ end
159
+
160
+ def drop_current(environment = env)
161
+ each_current_configuration(environment) { |configuration|
162
+ drop configuration
163
+ }
164
+ end
165
+
166
+ def migrate
167
+ check_target_version
168
+
169
+ verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] != "false" : true
170
+ scope = ENV["SCOPE"]
171
+ verbose_was, Migration.verbose = Migration.verbose, verbose
172
+ Base.connection.migration_context.migrate(target_version) do |migration|
173
+ scope.blank? || scope == migration.scope
174
+ end
175
+ ActiveRecord::Base.clear_cache!
176
+ ensure
177
+ Migration.verbose = verbose_was
178
+ end
179
+
180
+ def check_target_version
181
+ if target_version && !(Migration::MigrationFilenameRegexp.match?(ENV["VERSION"]) || /\A\d+\z/.match?(ENV["VERSION"]))
182
+ raise "Invalid format of target version: `VERSION=#{ENV['VERSION']}`"
183
+ end
184
+ end
185
+
186
+ def target_version
187
+ ENV["VERSION"].to_i if ENV["VERSION"] && !ENV["VERSION"].empty?
188
+ end
189
+
190
+ def charset_current(environment = env)
191
+ charset ActiveRecord::Base.configurations[environment]
192
+ end
193
+
194
+ def charset(*arguments)
195
+ configuration = arguments.first
196
+ class_for_adapter(configuration["adapter"]).new(*arguments).charset
197
+ end
198
+
199
+ def collation_current(environment = env)
200
+ collation ActiveRecord::Base.configurations[environment]
201
+ end
202
+
203
+ def collation(*arguments)
204
+ configuration = arguments.first
205
+ class_for_adapter(configuration["adapter"]).new(*arguments).collation
206
+ end
207
+
208
+ def purge(configuration)
209
+ class_for_adapter(configuration["adapter"]).new(configuration).purge
210
+ end
211
+
212
+ def purge_all
213
+ each_local_configuration { |configuration|
214
+ purge configuration
215
+ }
216
+ end
217
+
218
+ def purge_current(environment = env)
219
+ each_current_configuration(environment) { |configuration|
220
+ purge configuration
221
+ }
222
+ ActiveRecord::Base.establish_connection(environment.to_sym)
223
+ end
224
+
225
+ def structure_dump(*arguments)
226
+ configuration = arguments.first
227
+ filename = arguments.delete_at 1
228
+ class_for_adapter(configuration["adapter"]).new(*arguments).structure_dump(filename, structure_dump_flags)
229
+ end
230
+
231
+ def structure_load(*arguments)
232
+ configuration = arguments.first
233
+ filename = arguments.delete_at 1
234
+ class_for_adapter(configuration["adapter"]).new(*arguments).structure_load(filename, structure_load_flags)
235
+ end
236
+
237
+ def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env) # :nodoc:
238
+ file ||= schema_file(format)
239
+
240
+ check_schema_file(file)
241
+ ActiveRecord::Base.establish_connection(configuration)
242
+
243
+ case format
244
+ when :ruby
245
+ load(file)
246
+ when :sql
247
+ structure_load(configuration, file)
248
+ else
249
+ raise ArgumentError, "unknown format #{format.inspect}"
250
+ end
251
+ ActiveRecord::InternalMetadata.create_table
252
+ ActiveRecord::InternalMetadata[:environment] = environment
253
+ end
254
+
255
+ def schema_file(format = ActiveRecord::Base.schema_format)
256
+ case format
257
+ when :ruby
258
+ File.join(db_dir, "schema.rb")
259
+ when :sql
260
+ File.join(db_dir, "structure.sql")
261
+ end
262
+ end
263
+
264
+ def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
265
+ each_current_configuration(environment) { |configuration, configuration_environment|
266
+ load_schema configuration, format, file, configuration_environment
267
+ }
268
+ ActiveRecord::Base.establish_connection(environment.to_sym)
269
+ end
270
+
271
+ def check_schema_file(filename)
272
+ unless File.exist?(filename)
273
+ message = %{#{filename} doesn't exist yet. Run `rails db:migrate` to create it, then try again.}.dup
274
+ 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.root)
275
+ Kernel.abort message
276
+ end
277
+ end
278
+
279
+ def load_seed
280
+ if seed_loader
281
+ seed_loader.load_seed
282
+ else
283
+ raise "You tried to load seed data, but no seed loader is specified. Please specify seed " \
284
+ "loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n" \
285
+ "Seed loader should respond to load_seed method"
286
+ end
287
+ end
288
+
289
+ # Dumps the schema cache in YAML format for the connection into the file
290
+ #
291
+ # ==== Examples:
292
+ # ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, "tmp/schema_dump.yaml")
293
+ def dump_schema_cache(conn, filename)
294
+ conn.schema_cache.clear!
295
+ conn.data_sources.each { |table| conn.schema_cache.add(table) }
296
+ open(filename, "wb") { |f| f.write(YAML.dump(conn.schema_cache)) }
297
+ end
298
+
299
+ private
300
+
301
+ def class_for_adapter(adapter)
302
+ _key, task = @tasks.each_pair.detect { |pattern, _task| adapter[pattern] }
303
+ unless task
304
+ raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
305
+ end
306
+ task.is_a?(String) ? task.constantize : task
307
+ end
308
+
309
+ def each_current_configuration(environment)
310
+ environments = [environment]
311
+ environments << "test" if environment == "development"
312
+
313
+ ActiveRecord::Base.configurations.slice(*environments).each do |configuration_environment, configuration|
314
+ next unless configuration["database"]
315
+
316
+ yield configuration, configuration_environment
317
+ end
318
+ end
319
+
320
+ def each_local_configuration
321
+ ActiveRecord::Base.configurations.each_value do |configuration|
322
+ next unless configuration["database"]
323
+
324
+ if local_database?(configuration)
325
+ yield configuration
326
+ else
327
+ $stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host."
328
+ end
329
+ end
330
+ end
331
+
332
+ def local_database?(configuration)
333
+ configuration["host"].blank? || LOCAL_HOSTS.include?(configuration["host"])
334
+ end
335
+ end
336
+ end
337
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Tasks # :nodoc:
5
+ class MySQLDatabaseTasks # :nodoc:
6
+ delegate :connection, :establish_connection, to: ActiveRecord::Base
7
+
8
+ def initialize(configuration)
9
+ @configuration = configuration
10
+ end
11
+
12
+ def create
13
+ establish_connection configuration_without_database
14
+ connection.create_database configuration["database"], creation_options
15
+ establish_connection configuration
16
+ rescue ActiveRecord::StatementInvalid => error
17
+ if error.message.include?("database exists")
18
+ raise DatabaseAlreadyExists
19
+ else
20
+ raise
21
+ end
22
+ end
23
+
24
+ def drop
25
+ establish_connection configuration
26
+ connection.drop_database configuration["database"]
27
+ end
28
+
29
+ def purge
30
+ establish_connection configuration
31
+ connection.recreate_database configuration["database"], creation_options
32
+ end
33
+
34
+ def charset
35
+ connection.charset
36
+ end
37
+
38
+ def collation
39
+ connection.collation
40
+ end
41
+
42
+ def structure_dump(filename, extra_flags)
43
+ args = prepare_command_options
44
+ args.concat(["--result-file", "#{filename}"])
45
+ args.concat(["--no-data"])
46
+ args.concat(["--routines"])
47
+ args.concat(["--skip-comments"])
48
+
49
+ ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
50
+ if ignore_tables.any?
51
+ args += ignore_tables.map { |table| "--ignore-table=#{configuration['database']}.#{table}" }
52
+ end
53
+
54
+ args.concat(["#{configuration['database']}"])
55
+ args.unshift(*extra_flags) if extra_flags
56
+
57
+ run_cmd("mysqldump", args, "dumping")
58
+ end
59
+
60
+ def structure_load(filename, extra_flags)
61
+ args = prepare_command_options
62
+ args.concat(["--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
63
+ args.concat(["--database", "#{configuration['database']}"])
64
+ args.unshift(*extra_flags) if extra_flags
65
+
66
+ run_cmd("mysql", args, "loading")
67
+ end
68
+
69
+ private
70
+
71
+ def configuration
72
+ @configuration
73
+ end
74
+
75
+ def configuration_without_database
76
+ configuration.merge("database" => nil)
77
+ end
78
+
79
+ def creation_options
80
+ Hash.new.tap do |options|
81
+ options[:charset] = configuration["encoding"] if configuration.include? "encoding"
82
+ options[:collation] = configuration["collation"] if configuration.include? "collation"
83
+ end
84
+ end
85
+
86
+ def prepare_command_options
87
+ args = {
88
+ "host" => "--host",
89
+ "port" => "--port",
90
+ "socket" => "--socket",
91
+ "username" => "--user",
92
+ "password" => "--password",
93
+ "encoding" => "--default-character-set",
94
+ "sslca" => "--ssl-ca",
95
+ "sslcert" => "--ssl-cert",
96
+ "sslcapath" => "--ssl-capath",
97
+ "sslcipher" => "--ssl-cipher",
98
+ "sslkey" => "--ssl-key"
99
+ }.map { |opt, arg| "#{arg}=#{configuration[opt]}" if configuration[opt] }.compact
100
+
101
+ args
102
+ end
103
+
104
+ def run_cmd(cmd, args, action)
105
+ fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
106
+ end
107
+
108
+ def run_cmd_error(cmd, args, action)
109
+ msg = "failed to execute: `#{cmd}`\n".dup
110
+ 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"
111
+ msg
112
+ end
113
+ end
114
+ end
115
+ end