activerecord 3.2.19 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (264) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1715 -604
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +40 -45
  5. data/examples/performance.rb +33 -22
  6. data/examples/simple.rb +3 -4
  7. data/lib/active_record/aggregations.rb +76 -51
  8. data/lib/active_record/association_relation.rb +35 -0
  9. data/lib/active_record/associations/alias_tracker.rb +54 -40
  10. data/lib/active_record/associations/association.rb +76 -56
  11. data/lib/active_record/associations/association_scope.rb +125 -93
  12. data/lib/active_record/associations/belongs_to_association.rb +57 -28
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -2
  14. data/lib/active_record/associations/builder/association.rb +120 -32
  15. data/lib/active_record/associations/builder/belongs_to.rb +115 -62
  16. data/lib/active_record/associations/builder/collection_association.rb +61 -53
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +117 -43
  18. data/lib/active_record/associations/builder/has_many.rb +9 -65
  19. data/lib/active_record/associations/builder/has_one.rb +18 -52
  20. data/lib/active_record/associations/builder/singular_association.rb +18 -19
  21. data/lib/active_record/associations/collection_association.rb +268 -186
  22. data/lib/active_record/associations/collection_proxy.rb +1003 -63
  23. data/lib/active_record/associations/foreign_association.rb +11 -0
  24. data/lib/active_record/associations/has_many_association.rb +81 -41
  25. data/lib/active_record/associations/has_many_through_association.rb +76 -55
  26. data/lib/active_record/associations/has_one_association.rb +51 -21
  27. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  28. data/lib/active_record/associations/join_dependency/join_association.rb +83 -108
  29. data/lib/active_record/associations/join_dependency/join_base.rb +7 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +30 -37
  31. data/lib/active_record/associations/join_dependency.rb +239 -155
  32. data/lib/active_record/associations/preloader/association.rb +97 -62
  33. data/lib/active_record/associations/preloader/collection_association.rb +2 -8
  34. data/lib/active_record/associations/preloader/has_many_through.rb +7 -3
  35. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  36. data/lib/active_record/associations/preloader/singular_association.rb +3 -3
  37. data/lib/active_record/associations/preloader/through_association.rb +75 -33
  38. data/lib/active_record/associations/preloader.rb +111 -79
  39. data/lib/active_record/associations/singular_association.rb +35 -13
  40. data/lib/active_record/associations/through_association.rb +41 -19
  41. data/lib/active_record/associations.rb +727 -501
  42. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  43. data/lib/active_record/attribute.rb +213 -0
  44. data/lib/active_record/attribute_assignment.rb +32 -162
  45. data/lib/active_record/attribute_decorators.rb +67 -0
  46. data/lib/active_record/attribute_methods/before_type_cast.rb +52 -7
  47. data/lib/active_record/attribute_methods/dirty.rb +101 -61
  48. data/lib/active_record/attribute_methods/primary_key.rb +50 -36
  49. data/lib/active_record/attribute_methods/query.rb +7 -6
  50. data/lib/active_record/attribute_methods/read.rb +56 -117
  51. data/lib/active_record/attribute_methods/serialization.rb +43 -96
  52. data/lib/active_record/attribute_methods/time_zone_conversion.rb +93 -42
  53. data/lib/active_record/attribute_methods/write.rb +34 -45
  54. data/lib/active_record/attribute_methods.rb +333 -144
  55. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  56. data/lib/active_record/attribute_set/builder.rb +108 -0
  57. data/lib/active_record/attribute_set.rb +108 -0
  58. data/lib/active_record/attributes.rb +265 -0
  59. data/lib/active_record/autosave_association.rb +285 -223
  60. data/lib/active_record/base.rb +95 -490
  61. data/lib/active_record/callbacks.rb +95 -61
  62. data/lib/active_record/coders/json.rb +13 -0
  63. data/lib/active_record/coders/yaml_column.rb +28 -19
  64. data/lib/active_record/collection_cache_key.rb +40 -0
  65. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +724 -277
  66. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  67. data/lib/active_record/connection_adapters/abstract/database_statements.rb +199 -192
  68. data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -26
  69. data/lib/active_record/connection_adapters/abstract/quoting.rb +140 -57
  70. data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
  71. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +147 -0
  72. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +419 -276
  73. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +105 -0
  74. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +963 -276
  75. data/lib/active_record/connection_adapters/abstract/transaction.rb +232 -0
  76. data/lib/active_record/connection_adapters/abstract_adapter.rb +397 -106
  77. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +643 -342
  78. data/lib/active_record/connection_adapters/column.rb +30 -259
  79. data/lib/active_record/connection_adapters/connection_specification.rb +263 -0
  80. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  81. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  82. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  83. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  84. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  85. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  86. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  87. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  88. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  89. data/lib/active_record/connection_adapters/mysql2_adapter.rb +47 -196
  90. data/lib/active_record/connection_adapters/postgresql/column.rb +15 -0
  91. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +170 -0
  92. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +70 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +48 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +21 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +10 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +39 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +93 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -0
  110. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
  111. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  112. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  113. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  114. data/lib/active_record/connection_adapters/postgresql/oid.rb +31 -0
  115. data/lib/active_record/connection_adapters/postgresql/quoting.rb +116 -0
  116. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +49 -0
  117. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +180 -0
  118. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  119. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +682 -0
  120. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  121. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  122. data/lib/active_record/connection_adapters/postgresql_adapter.rb +558 -1039
  123. data/lib/active_record/connection_adapters/schema_cache.rb +74 -36
  124. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  125. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +538 -24
  129. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  130. data/lib/active_record/connection_handling.rb +155 -0
  131. data/lib/active_record/core.rb +561 -0
  132. data/lib/active_record/counter_cache.rb +146 -105
  133. data/lib/active_record/dynamic_matchers.rb +101 -64
  134. data/lib/active_record/enum.rb +234 -0
  135. data/lib/active_record/errors.rb +153 -56
  136. data/lib/active_record/explain.rb +15 -63
  137. data/lib/active_record/explain_registry.rb +30 -0
  138. data/lib/active_record/explain_subscriber.rb +10 -6
  139. data/lib/active_record/fixture_set/file.rb +77 -0
  140. data/lib/active_record/fixtures.rb +355 -232
  141. data/lib/active_record/gem_version.rb +15 -0
  142. data/lib/active_record/inheritance.rb +144 -79
  143. data/lib/active_record/integration.rb +66 -13
  144. data/lib/active_record/internal_metadata.rb +56 -0
  145. data/lib/active_record/legacy_yaml_adapter.rb +46 -0
  146. data/lib/active_record/locale/en.yml +9 -1
  147. data/lib/active_record/locking/optimistic.rb +77 -56
  148. data/lib/active_record/locking/pessimistic.rb +6 -6
  149. data/lib/active_record/log_subscriber.rb +53 -28
  150. data/lib/active_record/migration/command_recorder.rb +166 -33
  151. data/lib/active_record/migration/compatibility.rb +126 -0
  152. data/lib/active_record/migration/join_table.rb +15 -0
  153. data/lib/active_record/migration.rb +792 -264
  154. data/lib/active_record/model_schema.rb +192 -130
  155. data/lib/active_record/nested_attributes.rb +238 -145
  156. data/lib/active_record/no_touching.rb +52 -0
  157. data/lib/active_record/null_relation.rb +89 -0
  158. data/lib/active_record/persistence.rb +357 -157
  159. data/lib/active_record/query_cache.rb +22 -43
  160. data/lib/active_record/querying.rb +34 -23
  161. data/lib/active_record/railtie.rb +88 -48
  162. data/lib/active_record/railties/console_sandbox.rb +3 -4
  163. data/lib/active_record/railties/controller_runtime.rb +5 -4
  164. data/lib/active_record/railties/databases.rake +170 -422
  165. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  166. data/lib/active_record/readonly_attributes.rb +2 -5
  167. data/lib/active_record/reflection.rb +715 -189
  168. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  169. data/lib/active_record/relation/batches.rb +203 -50
  170. data/lib/active_record/relation/calculations.rb +203 -194
  171. data/lib/active_record/relation/delegation.rb +103 -25
  172. data/lib/active_record/relation/finder_methods.rb +457 -261
  173. data/lib/active_record/relation/from_clause.rb +32 -0
  174. data/lib/active_record/relation/merger.rb +167 -0
  175. data/lib/active_record/relation/predicate_builder/array_handler.rb +43 -0
  176. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  177. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  178. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  179. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  180. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  181. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  182. data/lib/active_record/relation/predicate_builder/relation_handler.rb +13 -0
  183. data/lib/active_record/relation/predicate_builder.rb +153 -48
  184. data/lib/active_record/relation/query_attribute.rb +19 -0
  185. data/lib/active_record/relation/query_methods.rb +1019 -194
  186. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  187. data/lib/active_record/relation/spawn_methods.rb +46 -150
  188. data/lib/active_record/relation/where_clause.rb +174 -0
  189. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  190. data/lib/active_record/relation.rb +450 -245
  191. data/lib/active_record/result.rb +104 -12
  192. data/lib/active_record/runtime_registry.rb +22 -0
  193. data/lib/active_record/sanitization.rb +120 -94
  194. data/lib/active_record/schema.rb +28 -18
  195. data/lib/active_record/schema_dumper.rb +141 -74
  196. data/lib/active_record/schema_migration.rb +50 -0
  197. data/lib/active_record/scoping/default.rb +64 -57
  198. data/lib/active_record/scoping/named.rb +93 -108
  199. data/lib/active_record/scoping.rb +73 -121
  200. data/lib/active_record/secure_token.rb +38 -0
  201. data/lib/active_record/serialization.rb +7 -5
  202. data/lib/active_record/statement_cache.rb +113 -0
  203. data/lib/active_record/store.rb +173 -15
  204. data/lib/active_record/suppressor.rb +58 -0
  205. data/lib/active_record/table_metadata.rb +68 -0
  206. data/lib/active_record/tasks/database_tasks.rb +313 -0
  207. data/lib/active_record/tasks/mysql_database_tasks.rb +151 -0
  208. data/lib/active_record/tasks/postgresql_database_tasks.rb +110 -0
  209. data/lib/active_record/tasks/sqlite_database_tasks.rb +59 -0
  210. data/lib/active_record/timestamp.rb +42 -24
  211. data/lib/active_record/touch_later.rb +58 -0
  212. data/lib/active_record/transactions.rb +233 -105
  213. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  214. data/lib/active_record/type/date.rb +7 -0
  215. data/lib/active_record/type/date_time.rb +7 -0
  216. data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
  217. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  218. data/lib/active_record/type/internal/timezone.rb +15 -0
  219. data/lib/active_record/type/serialized.rb +63 -0
  220. data/lib/active_record/type/time.rb +20 -0
  221. data/lib/active_record/type/type_map.rb +64 -0
  222. data/lib/active_record/type.rb +72 -0
  223. data/lib/active_record/type_caster/connection.rb +29 -0
  224. data/lib/active_record/type_caster/map.rb +19 -0
  225. data/lib/active_record/type_caster.rb +7 -0
  226. data/lib/active_record/validations/absence.rb +23 -0
  227. data/lib/active_record/validations/associated.rb +33 -18
  228. data/lib/active_record/validations/length.rb +24 -0
  229. data/lib/active_record/validations/presence.rb +66 -0
  230. data/lib/active_record/validations/uniqueness.rb +128 -68
  231. data/lib/active_record/validations.rb +48 -40
  232. data/lib/active_record/version.rb +5 -7
  233. data/lib/active_record.rb +71 -47
  234. data/lib/rails/generators/active_record/migration/migration_generator.rb +56 -8
  235. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +24 -0
  236. data/lib/rails/generators/active_record/migration/templates/migration.rb +28 -16
  237. data/lib/rails/generators/active_record/migration.rb +18 -8
  238. data/lib/rails/generators/active_record/model/model_generator.rb +38 -16
  239. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  240. data/lib/rails/generators/active_record/model/templates/model.rb +7 -6
  241. data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
  242. data/lib/rails/generators/active_record.rb +3 -11
  243. metadata +188 -134
  244. data/examples/associations.png +0 -0
  245. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
  246. data/lib/active_record/associations/join_helper.rb +0 -55
  247. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  248. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  249. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  250. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -441
  251. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  252. data/lib/active_record/dynamic_finder_match.rb +0 -68
  253. data/lib/active_record/dynamic_scope_match.rb +0 -23
  254. data/lib/active_record/fixtures/file.rb +0 -65
  255. data/lib/active_record/identity_map.rb +0 -162
  256. data/lib/active_record/observer.rb +0 -121
  257. data/lib/active_record/serializers/xml_serializer.rb +0 -203
  258. data/lib/active_record/session_store.rb +0 -360
  259. data/lib/active_record/test_case.rb +0 -73
  260. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
  261. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  262. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  263. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  264. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -0,0 +1,313 @@
1
+ require 'active_support/core_ext/string/filters'
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
+ extend self
39
+
40
+ attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
41
+ attr_accessor :database_configuration
42
+
43
+ LOCAL_HOSTS = ['127.0.0.1', 'localhost']
44
+
45
+ def check_protected_environments!
46
+ unless ENV['DISABLE_DATABASE_ENVIRONMENT_CHECK']
47
+ current = ActiveRecord::Migrator.current_environment
48
+ stored = ActiveRecord::Migrator.last_stored_environment
49
+
50
+ if ActiveRecord::Migrator.protected_environment?
51
+ raise ActiveRecord::ProtectedEnvironmentError.new(stored)
52
+ end
53
+
54
+ if stored && stored != current
55
+ raise ActiveRecord::EnvironmentMismatchError.new(current: current, stored: stored)
56
+ end
57
+ end
58
+ rescue ActiveRecord::NoDatabaseError
59
+ end
60
+
61
+ def register_task(pattern, task)
62
+ @tasks ||= {}
63
+ @tasks[pattern] = task
64
+ end
65
+
66
+ register_task(/mysql/, ActiveRecord::Tasks::MySQLDatabaseTasks)
67
+ register_task(/postgresql/, ActiveRecord::Tasks::PostgreSQLDatabaseTasks)
68
+ register_task(/sqlite/, ActiveRecord::Tasks::SQLiteDatabaseTasks)
69
+
70
+ def db_dir
71
+ @db_dir ||= Rails.application.config.paths["db"].first
72
+ end
73
+
74
+ def migrations_paths
75
+ @migrations_paths ||= Rails.application.paths['db/migrate'].to_a
76
+ end
77
+
78
+ def fixtures_path
79
+ @fixtures_path ||= if ENV['FIXTURES_PATH']
80
+ File.join(root, ENV['FIXTURES_PATH'])
81
+ else
82
+ File.join(root, 'test', 'fixtures')
83
+ end
84
+ end
85
+
86
+ def root
87
+ @root ||= Rails.root
88
+ end
89
+
90
+ def env
91
+ @env ||= Rails.env
92
+ end
93
+
94
+ def seed_loader
95
+ @seed_loader ||= Rails.application
96
+ end
97
+
98
+ def current_config(options = {})
99
+ options.reverse_merge! :env => env
100
+ if options.has_key?(:config)
101
+ @current_config = options[:config]
102
+ else
103
+ @current_config ||= ActiveRecord::Base.configurations[options[:env]]
104
+ end
105
+ end
106
+
107
+ def create(*arguments)
108
+ configuration = arguments.first
109
+ class_for_adapter(configuration['adapter']).new(*arguments).create
110
+ $stdout.puts "Created database '#{configuration['database']}'"
111
+ rescue DatabaseAlreadyExists
112
+ $stderr.puts "Database '#{configuration['database']}' already exists"
113
+ rescue Exception => error
114
+ $stderr.puts error
115
+ $stderr.puts "Couldn't create database for #{configuration.inspect}"
116
+ raise
117
+ end
118
+
119
+ def create_all
120
+ old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name)
121
+ each_local_configuration { |configuration| create configuration }
122
+ if old_pool
123
+ ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec)
124
+ end
125
+ end
126
+
127
+ def create_current(environment = env)
128
+ each_current_configuration(environment) { |configuration|
129
+ create configuration
130
+ }
131
+ ActiveRecord::Base.establish_connection(environment.to_sym)
132
+ end
133
+
134
+ def drop(*arguments)
135
+ configuration = arguments.first
136
+ class_for_adapter(configuration['adapter']).new(*arguments).drop
137
+ $stdout.puts "Dropped database '#{configuration['database']}'"
138
+ rescue ActiveRecord::NoDatabaseError
139
+ $stderr.puts "Database '#{configuration['database']}' does not exist"
140
+ rescue Exception => error
141
+ $stderr.puts error
142
+ $stderr.puts "Couldn't drop database '#{configuration['database']}'"
143
+ raise
144
+ end
145
+
146
+ def drop_all
147
+ each_local_configuration { |configuration| drop configuration }
148
+ end
149
+
150
+ def drop_current(environment = env)
151
+ each_current_configuration(environment) { |configuration|
152
+ drop configuration
153
+ }
154
+ end
155
+
156
+ def migrate
157
+ verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
158
+ version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
159
+ scope = ENV['SCOPE']
160
+ verbose_was, Migration.verbose = Migration.verbose, verbose
161
+ Migrator.migrate(migrations_paths, version) do |migration|
162
+ scope.blank? || scope == migration.scope
163
+ end
164
+ ActiveRecord::Base.clear_cache!
165
+ ensure
166
+ Migration.verbose = verbose_was
167
+ end
168
+
169
+ def charset_current(environment = env)
170
+ charset ActiveRecord::Base.configurations[environment]
171
+ end
172
+
173
+ def charset(*arguments)
174
+ configuration = arguments.first
175
+ class_for_adapter(configuration['adapter']).new(*arguments).charset
176
+ end
177
+
178
+ def collation_current(environment = env)
179
+ collation ActiveRecord::Base.configurations[environment]
180
+ end
181
+
182
+ def collation(*arguments)
183
+ configuration = arguments.first
184
+ class_for_adapter(configuration['adapter']).new(*arguments).collation
185
+ end
186
+
187
+ def purge(configuration)
188
+ class_for_adapter(configuration['adapter']).new(configuration).purge
189
+ end
190
+
191
+ def purge_all
192
+ each_local_configuration { |configuration|
193
+ purge configuration
194
+ }
195
+ end
196
+
197
+ def purge_current(environment = env)
198
+ each_current_configuration(environment) { |configuration|
199
+ purge configuration
200
+ }
201
+ ActiveRecord::Base.establish_connection(environment.to_sym)
202
+ end
203
+
204
+ def structure_dump(*arguments)
205
+ configuration = arguments.first
206
+ filename = arguments.delete_at 1
207
+ class_for_adapter(configuration['adapter']).new(*arguments).structure_dump(filename)
208
+ end
209
+
210
+ def structure_load(*arguments)
211
+ configuration = arguments.first
212
+ filename = arguments.delete_at 1
213
+ class_for_adapter(configuration['adapter']).new(*arguments).structure_load(filename)
214
+ end
215
+
216
+ def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
217
+ file ||= schema_file(format)
218
+
219
+ case format
220
+ when :ruby
221
+ check_schema_file(file)
222
+ ActiveRecord::Base.establish_connection(configuration)
223
+ load(file)
224
+ when :sql
225
+ check_schema_file(file)
226
+ structure_load(configuration, file)
227
+ else
228
+ raise ArgumentError, "unknown format #{format.inspect}"
229
+ end
230
+ ActiveRecord::InternalMetadata.create_table
231
+ ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment
232
+ end
233
+
234
+ def load_schema_for(*args)
235
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
236
+ This method was renamed to `#load_schema` and will be removed in the future.
237
+ Use `#load_schema` instead.
238
+ MSG
239
+ load_schema(*args)
240
+ end
241
+
242
+ def schema_file(format = ActiveRecord::Base.schema_format)
243
+ case format
244
+ when :ruby
245
+ File.join(db_dir, "schema.rb")
246
+ when :sql
247
+ File.join(db_dir, "structure.sql")
248
+ end
249
+ end
250
+
251
+ def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
252
+ each_current_configuration(environment) { |configuration|
253
+ load_schema configuration, format, file
254
+ }
255
+ ActiveRecord::Base.establish_connection(environment.to_sym)
256
+ end
257
+
258
+ def check_schema_file(filename)
259
+ unless File.exist?(filename)
260
+ message = %{#{filename} doesn't exist yet. Run `rails db:migrate` to create it, then try again.}
261
+ 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)
262
+ Kernel.abort message
263
+ end
264
+ end
265
+
266
+ def load_seed
267
+ if seed_loader
268
+ seed_loader.load_seed
269
+ else
270
+ raise "You tried to load seed data, but no seed loader is specified. Please specify seed " +
271
+ "loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n" +
272
+ "Seed loader should respond to load_seed method"
273
+ end
274
+ end
275
+
276
+ private
277
+
278
+ def class_for_adapter(adapter)
279
+ key = @tasks.keys.detect { |pattern| adapter[pattern] }
280
+ unless key
281
+ raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
282
+ end
283
+ @tasks[key]
284
+ end
285
+
286
+ def each_current_configuration(environment)
287
+ environments = [environment]
288
+ environments << 'test' if environment == 'development'
289
+
290
+ configurations = ActiveRecord::Base.configurations.values_at(*environments)
291
+ configurations.compact.each do |configuration|
292
+ yield configuration unless configuration['database'].blank?
293
+ end
294
+ end
295
+
296
+ def each_local_configuration
297
+ ActiveRecord::Base.configurations.each_value do |configuration|
298
+ next unless configuration['database']
299
+
300
+ if local_database?(configuration)
301
+ yield configuration
302
+ else
303
+ $stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host."
304
+ end
305
+ end
306
+ end
307
+
308
+ def local_database?(configuration)
309
+ configuration['host'].blank? || LOCAL_HOSTS.include?(configuration['host'])
310
+ end
311
+ end
312
+ end
313
+ end
@@ -0,0 +1,151 @@
1
+ module ActiveRecord
2
+ module Tasks # :nodoc:
3
+ class MySQLDatabaseTasks # :nodoc:
4
+ ACCESS_DENIED_ERROR = 1045
5
+
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 /database exists/ === error.message
18
+ raise DatabaseAlreadyExists
19
+ else
20
+ raise
21
+ end
22
+ rescue error_class => error
23
+ if error.respond_to?(:errno) && error.errno == ACCESS_DENIED_ERROR
24
+ $stdout.print error.message
25
+ establish_connection root_configuration_without_database
26
+ connection.create_database configuration['database'], creation_options
27
+ if configuration['username'] != 'root'
28
+ connection.execute grant_statement.gsub(/\s+/, ' ').strip
29
+ end
30
+ establish_connection configuration
31
+ else
32
+ $stderr.puts error.inspect
33
+ $stderr.puts "Couldn't create database for #{configuration.inspect}, #{creation_options.inspect}"
34
+ $stderr.puts "(If you set the charset manually, make sure you have a matching collation)" if configuration['encoding']
35
+ end
36
+ end
37
+
38
+ def drop
39
+ establish_connection configuration
40
+ connection.drop_database configuration['database']
41
+ end
42
+
43
+ def purge
44
+ establish_connection configuration
45
+ connection.recreate_database configuration['database'], creation_options
46
+ end
47
+
48
+ def charset
49
+ connection.charset
50
+ end
51
+
52
+ def collation
53
+ connection.collation
54
+ end
55
+
56
+ def structure_dump(filename)
57
+ args = prepare_command_options
58
+ args.concat(["--result-file", "#{filename}"])
59
+ args.concat(["--no-data"])
60
+ args.concat(["--routines"])
61
+ args.concat(["#{configuration['database']}"])
62
+
63
+ run_cmd('mysqldump', args, 'dumping')
64
+ end
65
+
66
+ def structure_load(filename)
67
+ args = prepare_command_options
68
+ args.concat(['--execute', %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
69
+ args.concat(["--database", "#{configuration['database']}"])
70
+
71
+ run_cmd('mysql', args, 'loading')
72
+ end
73
+
74
+ private
75
+
76
+ def configuration
77
+ @configuration
78
+ end
79
+
80
+ def configuration_without_database
81
+ configuration.merge('database' => nil)
82
+ end
83
+
84
+ def creation_options
85
+ Hash.new.tap do |options|
86
+ options[:charset] = configuration['encoding'] if configuration.include? 'encoding'
87
+ options[:collation] = configuration['collation'] if configuration.include? 'collation'
88
+ end
89
+ end
90
+
91
+ def error_class
92
+ if configuration['adapter'] =~ /jdbc/
93
+ require 'active_record/railties/jdbcmysql_error'
94
+ ArJdbcMySQL::Error
95
+ elsif defined?(Mysql2)
96
+ Mysql2::Error
97
+ else
98
+ StandardError
99
+ end
100
+ end
101
+
102
+ def grant_statement
103
+ <<-SQL
104
+ GRANT ALL PRIVILEGES ON #{configuration['database']}.*
105
+ TO '#{configuration['username']}'@'localhost'
106
+ IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
107
+ SQL
108
+ end
109
+
110
+ def root_configuration_without_database
111
+ configuration_without_database.merge(
112
+ 'username' => 'root',
113
+ 'password' => root_password
114
+ )
115
+ end
116
+
117
+ def root_password
118
+ $stdout.print "Please provide the root password for your MySQL installation\n>"
119
+ $stdin.gets.strip
120
+ end
121
+
122
+ def prepare_command_options
123
+ args = {
124
+ 'host' => '--host',
125
+ 'port' => '--port',
126
+ 'socket' => '--socket',
127
+ 'username' => '--user',
128
+ 'password' => '--password',
129
+ 'encoding' => '--default-character-set',
130
+ 'sslca' => '--ssl-ca',
131
+ 'sslcert' => '--ssl-cert',
132
+ 'sslcapath' => '--ssl-capath',
133
+ 'sslcipher' => '--ssl-cipher',
134
+ 'sslkey' => '--ssl-key'
135
+ }.map { |opt, arg| "#{arg}=#{configuration[opt]}" if configuration[opt] }.compact
136
+
137
+ args
138
+ end
139
+
140
+ def run_cmd(cmd, args, action)
141
+ fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
142
+ end
143
+
144
+ def run_cmd_error(cmd, args, action)
145
+ msg = "failed to execute: `#{cmd}`\n"
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"
147
+ msg
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,110 @@
1
+ module ActiveRecord
2
+ module Tasks # :nodoc:
3
+ class PostgreSQLDatabaseTasks # :nodoc:
4
+ DEFAULT_ENCODING = ENV['CHARSET'] || 'utf8'
5
+
6
+ delegate :connection, :establish_connection, :clear_active_connections!,
7
+ to: ActiveRecord::Base
8
+
9
+ def initialize(configuration)
10
+ @configuration = configuration
11
+ end
12
+
13
+ def create(master_established = false)
14
+ establish_master_connection unless master_established
15
+ connection.create_database configuration['database'],
16
+ configuration.merge('encoding' => encoding)
17
+ establish_connection configuration
18
+ rescue ActiveRecord::StatementInvalid => error
19
+ if /database .* already exists/ === error.message
20
+ raise DatabaseAlreadyExists
21
+ else
22
+ raise
23
+ end
24
+ end
25
+
26
+ def drop
27
+ establish_master_connection
28
+ connection.drop_database configuration['database']
29
+ end
30
+
31
+ def charset
32
+ connection.encoding
33
+ end
34
+
35
+ def collation
36
+ connection.collation
37
+ end
38
+
39
+ def purge
40
+ clear_active_connections!
41
+ drop
42
+ create true
43
+ end
44
+
45
+ def structure_dump(filename)
46
+ set_psql_env
47
+
48
+ search_path = case ActiveRecord::Base.dump_schemas
49
+ when :schema_search_path
50
+ configuration['schema_search_path']
51
+ when :all
52
+ nil
53
+ when String
54
+ ActiveRecord::Base.dump_schemas
55
+ end
56
+
57
+ args = ['-s', '-x', '-O', '-f', filename]
58
+ unless search_path.blank?
59
+ args += search_path.split(',').map do |part|
60
+ "--schema=#{part.strip}"
61
+ end
62
+ end
63
+ args << configuration['database']
64
+ run_cmd('pg_dump', args, 'dumping')
65
+ File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
66
+ end
67
+
68
+ def structure_load(filename)
69
+ set_psql_env
70
+ args = [ '-q', '-f', filename, configuration['database'] ]
71
+ run_cmd('psql', args, 'loading' )
72
+ end
73
+
74
+ private
75
+
76
+ def configuration
77
+ @configuration
78
+ end
79
+
80
+ def encoding
81
+ configuration['encoding'] || DEFAULT_ENCODING
82
+ end
83
+
84
+ def establish_master_connection
85
+ establish_connection configuration.merge(
86
+ 'database' => 'postgres',
87
+ 'schema_search_path' => 'public'
88
+ )
89
+ end
90
+
91
+ def set_psql_env
92
+ ENV['PGHOST'] = configuration['host'] if configuration['host']
93
+ ENV['PGPORT'] = configuration['port'].to_s if configuration['port']
94
+ ENV['PGPASSWORD'] = configuration['password'].to_s if configuration['password']
95
+ ENV['PGUSER'] = configuration['username'].to_s if configuration['username']
96
+ end
97
+
98
+ def run_cmd(cmd, args, action)
99
+ fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
100
+ end
101
+
102
+ def run_cmd_error(cmd, args, action)
103
+ msg = "failed to execute:\n"
104
+ msg << "#{cmd} #{args.join(' ')}\n\n"
105
+ 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"
106
+ msg
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,59 @@
1
+ module ActiveRecord
2
+ module Tasks # :nodoc:
3
+ class SQLiteDatabaseTasks # :nodoc:
4
+ delegate :connection, :establish_connection, to: ActiveRecord::Base
5
+
6
+ def initialize(configuration, root = ActiveRecord::Tasks::DatabaseTasks.root)
7
+ @configuration, @root = configuration, root
8
+ end
9
+
10
+ def create
11
+ raise DatabaseAlreadyExists if File.exist?(configuration['database'])
12
+
13
+ establish_connection configuration
14
+ connection
15
+ end
16
+
17
+ def drop
18
+ require 'pathname'
19
+ path = Pathname.new configuration['database']
20
+ file = path.absolute? ? path.to_s : File.join(root, path)
21
+
22
+ FileUtils.rm(file)
23
+ rescue Errno::ENOENT => error
24
+ raise NoDatabaseError.new(error.message, error)
25
+ end
26
+
27
+ def purge
28
+ drop
29
+ rescue NoDatabaseError
30
+ ensure
31
+ create
32
+ end
33
+
34
+ def charset
35
+ connection.encoding
36
+ end
37
+
38
+ def structure_dump(filename)
39
+ dbfile = configuration['database']
40
+ `sqlite3 #{dbfile} .schema > #{filename}`
41
+ end
42
+
43
+ def structure_load(filename)
44
+ dbfile = configuration['database']
45
+ `sqlite3 #{dbfile} < "#{filename}"`
46
+ end
47
+
48
+ private
49
+
50
+ def configuration
51
+ @configuration
52
+ end
53
+
54
+ def root
55
+ @root
56
+ end
57
+ end
58
+ end
59
+ end