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
@@ -1,207 +1,73 @@
1
- require 'active_support/core_ext/object/inclusion'
2
1
  require 'active_record'
3
2
 
4
3
  db_namespace = namespace :db do
5
- def database_url_config
6
- @database_url_config ||=
7
- ActiveRecord::Base::ConnectionSpecification::Resolver.new(ENV["DATABASE_URL"], {}).spec.config.stringify_keys
4
+ desc "Set the environment value for the database"
5
+ task "environment:set" => [:environment, :load_config] do
6
+ ActiveRecord::InternalMetadata.create_table
7
+ ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment
8
8
  end
9
9
 
10
- def current_config(options = {})
11
- options = { :env => Rails.env }.merge! options
12
-
13
- if options[:config]
14
- @current_config = options[:config]
15
- else
16
- @current_config ||= if ENV['DATABASE_URL']
17
- database_url_config
18
- else
19
- ActiveRecord::Base.configurations[options[:env]]
20
- end
21
- end
10
+ task :check_protected_environments => [:environment, :load_config] do
11
+ ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
22
12
  end
23
13
 
24
14
  task :load_config do
25
- ActiveRecord::Base.configurations = Rails.application.config.database_configuration
26
- ActiveRecord::Migrator.migrations_paths = Rails.application.paths['db/migrate'].to_a
27
-
28
- if defined?(ENGINE_PATH) && engine = Rails::Engine.find(ENGINE_PATH)
29
- if engine.paths['db/migrate'].existent
30
- ActiveRecord::Migrator.migrations_paths += engine.paths['db/migrate'].to_a
31
- end
32
- end
15
+ ActiveRecord::Base.configurations = ActiveRecord::Tasks::DatabaseTasks.database_configuration || {}
16
+ ActiveRecord::Migrator.migrations_paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
33
17
  end
34
18
 
35
19
  namespace :create do
36
- # desc 'Create all the local databases defined in config/database.yml'
37
20
  task :all => :load_config do
38
- ActiveRecord::Base.configurations.each_value do |config|
39
- # Skip entries that don't have a database key, such as the first entry here:
40
- #
41
- # defaults: &defaults
42
- # adapter: mysql
43
- # username: root
44
- # password:
45
- # host: localhost
46
- #
47
- # development:
48
- # database: blog_development
49
- # *defaults
50
- next unless config['database']
51
- # Only connect to local databases
52
- local_database?(config) { create_database(config) }
53
- end
21
+ ActiveRecord::Tasks::DatabaseTasks.create_all
54
22
  end
55
23
  end
56
24
 
57
- desc 'Create the database from DATABASE_URL or config/database.yml for the current Rails.env (use db:create:all to create all dbs in the config)'
58
- task :create => [:load_config, :rails_env] do
59
- if ENV['DATABASE_URL']
60
- create_database(database_url_config)
61
- else
62
- configs_for_environment.each { |config| create_database(config) }
63
- ActiveRecord::Base.establish_connection(configs_for_environment.first)
64
- end
25
+ 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.'
26
+ task :create => [:load_config] do
27
+ ActiveRecord::Tasks::DatabaseTasks.create_current
65
28
  end
66
29
 
67
- # If neither encoding nor collation is specified, use the utf-8 defaults.
68
- def mysql_creation_options(config)
69
- default_charset = ENV['CHARSET'] || 'utf8'
70
- default_collation = ENV['COLLATION'] || 'utf8_unicode_ci'
71
-
72
- Hash.new.tap do |options|
73
- options[:charset] = config['encoding'] if config.include? 'encoding'
74
- options[:collation] = config['collation'] if config.include? 'collation'
75
-
76
- # Set default charset only when collation isn't set.
77
- options[:charset] ||= default_charset unless options[:collation]
78
-
79
- # Set default collation only when charset is also default.
80
- options[:collation] ||= default_collation if options[:charset] == default_charset
30
+ namespace :drop do
31
+ task :all => [:load_config, :check_protected_environments] do
32
+ ActiveRecord::Tasks::DatabaseTasks.drop_all
81
33
  end
82
34
  end
83
35
 
84
- def create_database(config)
85
- begin
86
- if config['adapter'] =~ /sqlite/
87
- if File.exist?(config['database'])
88
- $stderr.puts "#{config['database']} already exists"
89
- else
90
- begin
91
- # Create the SQLite database
92
- ActiveRecord::Base.establish_connection(config)
93
- ActiveRecord::Base.connection
94
- rescue Exception => e
95
- $stderr.puts e, *(e.backtrace)
96
- $stderr.puts "Couldn't create database for #{config.inspect}"
97
- end
98
- end
99
- return # Skip the else clause of begin/rescue
100
- else
101
- ActiveRecord::Base.establish_connection(config)
102
- ActiveRecord::Base.connection
103
- end
104
- rescue
105
- case config['adapter']
106
- when /mysql/
107
- if config['adapter'] =~ /jdbc/
108
- #FIXME After Jdbcmysql gives this class
109
- require 'active_record/railties/jdbcmysql_error'
110
- error_class = ArJdbcMySQL::Error
111
- else
112
- error_class = config['adapter'] =~ /mysql2/ ? Mysql2::Error : Mysql::Error
113
- end
114
- access_denied_error = 1045
115
-
116
- create_options = mysql_creation_options(config)
117
-
118
- begin
119
- ActiveRecord::Base.establish_connection(config.merge('database' => nil))
120
- ActiveRecord::Base.connection.create_database(config['database'], create_options)
121
- ActiveRecord::Base.establish_connection(config)
122
- rescue error_class => sqlerr
123
- if sqlerr.errno == access_denied_error
124
- print "#{sqlerr.error}. \nPlease provide the root password for your mysql installation\n>"
125
- root_password = $stdin.gets.strip
126
- grant_statement = "GRANT ALL PRIVILEGES ON #{config['database']}.* " \
127
- "TO '#{config['username']}'@'localhost' " \
128
- "IDENTIFIED BY '#{config['password']}' WITH GRANT OPTION;"
129
- ActiveRecord::Base.establish_connection(config.merge(
130
- 'database' => nil, 'username' => 'root', 'password' => root_password))
131
- ActiveRecord::Base.connection.create_database(config['database'], mysql_creation_options(config))
132
- ActiveRecord::Base.connection.execute grant_statement
133
- ActiveRecord::Base.establish_connection(config)
134
- else
135
- $stderr.puts sqlerr.error
136
- $stderr.puts "Couldn't create database for #{config.inspect}, charset: #{create_options[:charset]}, collation: #{create_options[:collation]}"
137
- $stderr.puts "(if you set the charset manually, make sure you have a matching collation)" if config['encoding']
138
- end
139
- end
140
- when /postgresql/
141
- @encoding = config['encoding'] || ENV['CHARSET'] || 'utf8'
142
- begin
143
- ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
144
- ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => @encoding))
145
- ActiveRecord::Base.establish_connection(config)
146
- rescue Exception => e
147
- $stderr.puts e, *(e.backtrace)
148
- $stderr.puts "Couldn't create database for #{config.inspect}"
149
- end
150
- end
151
- else
152
- # Bug with 1.9.2 Calling return within begin still executes else
153
- $stderr.puts "#{config['database']} already exists" unless config['adapter'] =~ /sqlite/
154
- end
36
+ 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.'
37
+ task :drop => [:load_config, :check_protected_environments] do
38
+ db_namespace["drop:_unsafe"].invoke
155
39
  end
156
40
 
157
- namespace :drop do
158
- # desc 'Drops all the local databases defined in config/database.yml'
159
- task :all => :load_config do
160
- ActiveRecord::Base.configurations.each_value do |config|
161
- # Skip entries that don't have a database key
162
- next unless config['database']
163
- begin
164
- # Only connect to local databases
165
- local_database?(config) { drop_database(config) }
166
- rescue Exception => e
167
- $stderr.puts "Couldn't drop #{config['database']} : #{e.inspect}"
168
- end
169
- end
170
- end
41
+ task "drop:_unsafe" => [:load_config] do
42
+ ActiveRecord::Tasks::DatabaseTasks.drop_current
171
43
  end
172
44
 
173
- desc 'Drops the database using DATABASE_URL or the current Rails.env (use db:drop:all to drop all databases)'
174
- task :drop => [:load_config, :rails_env] do
175
- if ENV['DATABASE_URL']
176
- drop_database_and_rescue(database_url_config)
177
- else
178
- configs_for_environment.each { |config| drop_database_and_rescue(config) }
45
+ namespace :purge do
46
+ task :all => [:load_config, :check_protected_environments] do
47
+ ActiveRecord::Tasks::DatabaseTasks.purge_all
179
48
  end
180
49
  end
181
50
 
182
- def local_database?(config, &block)
183
- if config['host'].in?(['127.0.0.1', 'localhost']) || config['host'].blank?
184
- yield
185
- else
186
- $stderr.puts "This task only modifies local databases. #{config['database']} is on a remote host."
187
- end
51
+ # 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."
52
+ task :purge => [:load_config, :check_protected_environments] do
53
+ ActiveRecord::Tasks::DatabaseTasks.purge_current
188
54
  end
189
55
 
190
- desc "Migrate the database (options: VERSION=x, VERBOSE=false)."
56
+ desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
191
57
  task :migrate => [:environment, :load_config] do
192
- ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
193
- ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, ENV["VERSION"] ? ENV["VERSION"].to_i : nil) do |migration|
194
- ENV["SCOPE"].blank? || (ENV["SCOPE"] == migration.scope)
195
- end
58
+ ActiveRecord::Tasks::DatabaseTasks.migrate
196
59
  db_namespace['_dump'].invoke
197
60
  end
198
61
 
62
+ # IMPORTANT: This task won't dump the schema if ActiveRecord::Base.dump_schema_after_migration is set to false
199
63
  task :_dump do
200
- case ActiveRecord::Base.schema_format
201
- when :ruby then db_namespace["schema:dump"].invoke
202
- when :sql then db_namespace["structure:dump"].invoke
203
- else
204
- raise "unknown schema format #{ActiveRecord::Base.schema_format}"
64
+ if ActiveRecord::Base.dump_schema_after_migration
65
+ case ActiveRecord::Base.schema_format
66
+ when :ruby then db_namespace["schema:dump"].invoke
67
+ when :sql then db_namespace["structure:dump"].invoke
68
+ else
69
+ raise "unknown schema format #{ActiveRecord::Base.schema_format}"
70
+ end
205
71
  end
206
72
  # Allow this task to be called as many times as required. An example is the
207
73
  # migrate:redo task, which calls other two internally that depend on this one.
@@ -227,35 +93,37 @@ db_namespace = namespace :db do
227
93
  task :up => [:environment, :load_config] do
228
94
  version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
229
95
  raise 'VERSION is required' unless version
230
- ActiveRecord::Migrator.run(:up, ActiveRecord::Migrator.migrations_paths, version)
96
+ ActiveRecord::Migrator.run(:up, ActiveRecord::Tasks::DatabaseTasks.migrations_paths, version)
231
97
  db_namespace['_dump'].invoke
232
98
  end
233
99
 
234
100
  # desc 'Runs the "down" for a given migration VERSION.'
235
101
  task :down => [:environment, :load_config] do
236
102
  version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
237
- raise 'VERSION is required' unless version
238
- ActiveRecord::Migrator.run(:down, ActiveRecord::Migrator.migrations_paths, version)
103
+ raise 'VERSION is required - To go down one migration, run db:rollback' unless version
104
+ ActiveRecord::Migrator.run(:down, ActiveRecord::Tasks::DatabaseTasks.migrations_paths, version)
239
105
  db_namespace['_dump'].invoke
240
106
  end
241
107
 
242
108
  desc 'Display status of migrations'
243
109
  task :status => [:environment, :load_config] do
244
- unless ActiveRecord::Base.connection.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
245
- puts 'Schema migrations table does not exist yet.'
246
- next # means "return" for rake task
110
+ unless ActiveRecord::SchemaMigration.table_exists?
111
+ abort 'Schema migrations table does not exist yet.'
247
112
  end
248
- db_list = ActiveRecord::Base.connection.select_values("SELECT version FROM #{ActiveRecord::Migrator.schema_migrations_table_name}")
249
- file_list = []
250
- ActiveRecord::Migrator.migrations_paths.each do |path|
251
- Dir.foreach(path) do |file|
252
- # only files matching "20091231235959_some_name.rb" pattern
253
- if match_data = /^(\d{14})_(.+)\.rb$/.match(file)
254
- status = db_list.delete(match_data[1]) ? 'up' : 'down'
255
- file_list << [status, match_data[1], match_data[2].humanize]
113
+ db_list = ActiveRecord::SchemaMigration.normalized_versions
114
+
115
+ file_list =
116
+ ActiveRecord::Tasks::DatabaseTasks.migrations_paths.flat_map do |path|
117
+ Dir.foreach(path).map do |file|
118
+ next unless ActiveRecord::Migrator.match_to_migration_filename?(file)
119
+
120
+ version, name, scope = ActiveRecord::Migrator.parse_migration_filename(file)
121
+ version = ActiveRecord::SchemaMigration.normalize_migration_number(version)
122
+ status = db_list.delete(version) ? 'up' : 'down'
123
+ [status, version, (name + scope).humanize]
124
+ end.compact
256
125
  end
257
- end
258
- end
126
+
259
127
  db_list.map! do |version|
260
128
  ['up', version, '********** NO FILE **********']
261
129
  end
@@ -263,8 +131,8 @@ db_namespace = namespace :db do
263
131
  puts "\ndatabase: #{ActiveRecord::Base.connection_config[:database]}\n\n"
264
132
  puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
265
133
  puts "-" * 50
266
- (db_list + file_list).sort_by {|migration| migration[1]}.each do |migration|
267
- puts "#{migration[0].center(8)} #{migration[1].ljust(14)} #{migration[2]}"
134
+ (db_list + file_list).sort_by { |_, version, _| version }.each do |status, version, name|
135
+ puts "#{status.center(8)} #{version.ljust(14)} #{name}"
268
136
  end
269
137
  puts
270
138
  end
@@ -273,50 +141,31 @@ db_namespace = namespace :db do
273
141
  desc 'Rolls the schema back to the previous version (specify steps w/ STEP=n).'
274
142
  task :rollback => [:environment, :load_config] do
275
143
  step = ENV['STEP'] ? ENV['STEP'].to_i : 1
276
- ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_paths, step)
144
+ ActiveRecord::Migrator.rollback(ActiveRecord::Tasks::DatabaseTasks.migrations_paths, step)
277
145
  db_namespace['_dump'].invoke
278
146
  end
279
147
 
280
148
  # desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
281
149
  task :forward => [:environment, :load_config] do
282
150
  step = ENV['STEP'] ? ENV['STEP'].to_i : 1
283
- ActiveRecord::Migrator.forward(ActiveRecord::Migrator.migrations_paths, step)
151
+ ActiveRecord::Migrator.forward(ActiveRecord::Tasks::DatabaseTasks.migrations_paths, step)
284
152
  db_namespace['_dump'].invoke
285
153
  end
286
154
 
287
155
  # desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.'
288
- task :reset => [:environment, :load_config] do
289
- db_namespace["drop"].invoke
290
- db_namespace["setup"].invoke
291
- end
156
+ task :reset => [ 'db:drop', 'db:setup' ]
292
157
 
293
158
  # desc "Retrieves the charset for the current environment's database"
294
159
  task :charset => [:environment, :load_config] do
295
- config = ActiveRecord::Base.configurations[Rails.env]
296
- case config['adapter']
297
- when /mysql/
298
- ActiveRecord::Base.establish_connection(config)
299
- puts ActiveRecord::Base.connection.charset
300
- when /postgresql/
301
- ActiveRecord::Base.establish_connection(config)
302
- puts ActiveRecord::Base.connection.encoding
303
- when /sqlite/
304
- ActiveRecord::Base.establish_connection(config)
305
- puts ActiveRecord::Base.connection.encoding
306
- else
307
- $stderr.puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
308
- end
160
+ puts ActiveRecord::Tasks::DatabaseTasks.charset_current
309
161
  end
310
162
 
311
163
  # desc "Retrieves the collation for the current environment's database"
312
164
  task :collation => [:environment, :load_config] do
313
- config = ActiveRecord::Base.configurations[Rails.env]
314
- case config['adapter']
315
- when /mysql/
316
- ActiveRecord::Base.establish_connection(config)
317
- puts ActiveRecord::Base.connection.collation
318
- else
319
- $stderr.puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
165
+ begin
166
+ puts ActiveRecord::Tasks::DatabaseTasks.collation_current
167
+ rescue NoMethodError
168
+ $stderr.puts 'Sorry, your database adapter is not supported yet. Feel free to submit a patch.'
320
169
  end
321
170
  end
322
171
 
@@ -327,37 +176,47 @@ db_namespace = namespace :db do
327
176
 
328
177
  # desc "Raises an error if there are pending migrations"
329
178
  task :abort_if_pending_migrations => [:environment, :load_config] do
330
- pending_migrations = ActiveRecord::Migrator.new(:up, ActiveRecord::Migrator.migrations_paths).pending_migrations
179
+ pending_migrations = ActiveRecord::Migrator.open(ActiveRecord::Tasks::DatabaseTasks.migrations_paths).pending_migrations
331
180
 
332
181
  if pending_migrations.any?
333
- puts "You have #{pending_migrations.size} pending migrations:"
182
+ puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
334
183
  pending_migrations.each do |pending_migration|
335
184
  puts ' %4d %s' % [pending_migration.version, pending_migration.name]
336
185
  end
337
- abort %{Run `rake db:migrate` to update your database then try again.}
186
+ abort %{Run `rails db:migrate` to update your database then try again.}
338
187
  end
339
188
  end
340
189
 
341
- desc 'Create the database, load the schema, and initialize with the seed data (use db:reset to also drop the db first)'
190
+ desc 'Creates the database, loads the schema, and initializes with the seed data (use db:reset to also drop the database first)'
342
191
  task :setup => ['db:schema:load_if_ruby', 'db:structure:load_if_sql', :seed]
343
192
 
344
- desc 'Load the seed data from db/seeds.rb'
193
+ desc 'Loads the seed data from db/seeds.rb'
345
194
  task :seed do
346
195
  db_namespace['abort_if_pending_migrations'].invoke
347
- Rails.application.load_seed
196
+ ActiveRecord::Tasks::DatabaseTasks.load_seed
348
197
  end
349
198
 
350
199
  namespace :fixtures do
351
- desc "Load 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."
200
+ 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."
352
201
  task :load => [:environment, :load_config] do
353
202
  require 'active_record/fixtures'
354
203
 
355
- base_dir = File.join [Rails.root, ENV['FIXTURES_PATH'] || %w{test fixtures}].flatten
356
- fixtures_dir = File.join [base_dir, ENV['FIXTURES_DIR']].compact
204
+ base_dir = ActiveRecord::Tasks::DatabaseTasks.fixtures_path
357
205
 
358
- (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir["#{fixtures_dir}/**/*.yml"].map {|f| f[(fixtures_dir.size + 1)..-5] }).each do |fixture_file|
359
- ActiveRecord::Fixtures.create_fixtures(fixtures_dir, fixture_file)
360
- end
206
+ fixtures_dir = if ENV['FIXTURES_DIR']
207
+ File.join base_dir, ENV['FIXTURES_DIR']
208
+ else
209
+ base_dir
210
+ end
211
+
212
+ fixture_files = if ENV['FIXTURES']
213
+ ENV['FIXTURES'].split(',')
214
+ else
215
+ # The use of String#[] here is to support namespaced fixtures
216
+ Dir["#{fixtures_dir}/**/*.yml"].map {|f| f[(fixtures_dir.size + 1)..-5] }
217
+ end
218
+
219
+ ActiveRecord::FixtureSet.create_fixtures(fixtures_dir, fixture_files)
361
220
  end
362
221
 
363
222
  # desc "Search for a fixture given a LABEL or ID. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
@@ -367,13 +226,14 @@ db_namespace = namespace :db do
367
226
  label, id = ENV['LABEL'], ENV['ID']
368
227
  raise 'LABEL or ID required' if label.blank? && id.blank?
369
228
 
370
- puts %Q(The fixture ID for "#{label}" is #{ActiveRecord::Fixtures.identify(label)}.) if label
229
+ puts %Q(The fixture ID for "#{label}" is #{ActiveRecord::FixtureSet.identify(label)}.) if label
230
+
231
+ base_dir = ActiveRecord::Tasks::DatabaseTasks.fixtures_path
371
232
 
372
- base_dir = ENV['FIXTURES_PATH'] ? File.join(Rails.root, ENV['FIXTURES_PATH']) : File.join(Rails.root, 'test', 'fixtures')
373
233
  Dir["#{base_dir}/**/*.yml"].each do |file|
374
234
  if data = YAML::load(ERB.new(IO.read(file)).result)
375
- data.keys.each do |key|
376
- key_id = ActiveRecord::Fixtures.identify(key)
235
+ data.each_key do |key|
236
+ key_id = ActiveRecord::FixtureSet.identify(key)
377
237
 
378
238
  if key == label || key_id == id.to_i
379
239
  puts "#{file}: #{key} (#{key_id})"
@@ -385,99 +245,65 @@ db_namespace = namespace :db do
385
245
  end
386
246
 
387
247
  namespace :schema do
388
- desc 'Create a db/schema.rb file that can be portably used against any DB supported by AR'
248
+ desc 'Creates a db/schema.rb file that is portable against any DB supported by Active Record'
389
249
  task :dump => [:environment, :load_config] do
390
250
  require 'active_record/schema_dumper'
391
- filename = ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb"
251
+ filename = ENV['SCHEMA'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'schema.rb')
392
252
  File.open(filename, "w:utf-8") do |file|
393
253
  ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
394
254
  end
395
255
  db_namespace['schema:dump'].reenable
396
256
  end
397
257
 
398
- desc 'Load a schema.rb file into the database'
399
- task :load => [:environment, :load_config] do
400
- file = ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb"
401
- if File.exists?(file)
402
- load(file)
403
- else
404
- abort %{#{file} doesn't exist yet. Run `rake db:migrate` to create it then try again. 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}
405
- end
258
+ desc 'Loads a schema.rb file into the database'
259
+ task :load => [:environment, :load_config, :check_protected_environments] do
260
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:ruby, ENV['SCHEMA'])
406
261
  end
407
262
 
408
263
  task :load_if_ruby => ['db:create', :environment] do
409
264
  db_namespace["schema:load"].invoke if ActiveRecord::Base.schema_format == :ruby
410
265
  end
266
+
267
+ namespace :cache do
268
+ desc 'Creates a db/schema_cache.dump file.'
269
+ task :dump => [:environment, :load_config] do
270
+ con = ActiveRecord::Base.connection
271
+ filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.dump")
272
+
273
+ con.schema_cache.clear!
274
+ con.data_sources.each { |table| con.schema_cache.add(table) }
275
+ open(filename, 'wb') { |f| f.write(Marshal.dump(con.schema_cache)) }
276
+ end
277
+
278
+ desc 'Clears a db/schema_cache.dump file.'
279
+ task :clear => [:environment, :load_config] do
280
+ filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.dump")
281
+ rm_f filename, verbose: false
282
+ end
283
+ end
284
+
411
285
  end
412
286
 
413
287
  namespace :structure do
414
- desc 'Dump the database structure to db/structure.sql. Specify another file with DB_STRUCTURE=db/my_structure.sql'
288
+ desc 'Dumps the database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql'
415
289
  task :dump => [:environment, :load_config] do
416
- config = current_config
417
- filename = ENV['DB_STRUCTURE'] || File.join(Rails.root, "db", "structure.sql")
418
- case config['adapter']
419
- when /mysql/, 'oci', 'oracle'
420
- ActiveRecord::Base.establish_connection(config)
421
- File.open(filename, "w:utf-8") { |f| f << ActiveRecord::Base.connection.structure_dump }
422
- when /postgresql/
423
- set_psql_env(config)
424
- search_path = config['schema_search_path']
425
- unless search_path.blank?
426
- search_path = search_path.split(",").map{|search_path_part| "--schema=#{Shellwords.escape(search_path_part.strip)}" }.join(" ")
290
+ filename = ENV['SCHEMA'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql")
291
+ current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
292
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(current_config, filename)
293
+
294
+ if ActiveRecord::Base.connection.supports_migrations? &&
295
+ ActiveRecord::SchemaMigration.table_exists?
296
+ File.open(filename, "a") do |f|
297
+ f.puts ActiveRecord::Base.connection.dump_schema_information
298
+ f.print "\n"
427
299
  end
428
- `pg_dump -i -s -x -O -f #{Shellwords.escape(filename)} #{search_path} #{Shellwords.escape(config['database'])}`
429
- raise 'Error dumping database' if $?.exitstatus == 1
430
- File.open(filename, "a") { |f| f << "SET search_path TO #{ActiveRecord::Base.connection.schema_search_path};\n\n" }
431
- when /sqlite/
432
- dbfile = config['database']
433
- `sqlite3 #{dbfile} .schema > #{filename}`
434
- when 'sqlserver'
435
- `smoscript -s #{config['host']} -d #{config['database']} -u #{config['username']} -p #{config['password']} -f #{filename} -A -U`
436
- when "firebird"
437
- set_firebird_env(config)
438
- db_string = firebird_db_string(config)
439
- sh "isql -a #{db_string} > #{filename}"
440
- else
441
- raise "Task not supported by '#{config['adapter']}'"
442
- end
443
-
444
- if ActiveRecord::Base.connection.supports_migrations?
445
- File.open(filename, "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information }
446
300
  end
447
301
  db_namespace['structure:dump'].reenable
448
302
  end
449
303
 
450
- # desc "Recreate the databases from the structure.sql file"
451
- task :load => [:environment, :load_config] do
452
- config = current_config
453
- filename = ENV['DB_STRUCTURE'] || File.join(Rails.root, "db", "structure.sql")
454
- case config['adapter']
455
- when /mysql/
456
- ActiveRecord::Base.establish_connection(config)
457
- ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
458
- IO.read(filename).split("\n\n").each do |table|
459
- ActiveRecord::Base.connection.execute(table)
460
- end
461
- when /postgresql/
462
- set_psql_env(config)
463
- `psql -f "#{filename}" #{config['database']}`
464
- when /sqlite/
465
- dbfile = config['database']
466
- `sqlite3 #{dbfile} < "#{filename}"`
467
- when 'sqlserver'
468
- `sqlcmd -S #{config['host']} -d #{config['database']} -U #{config['username']} -P #{config['password']} -i #{filename}`
469
- when 'oci', 'oracle'
470
- ActiveRecord::Base.establish_connection(config)
471
- IO.read(filename).split(";\n\n").each do |ddl|
472
- ActiveRecord::Base.connection.execute(ddl)
473
- end
474
- when 'firebird'
475
- set_firebird_env(config)
476
- db_string = firebird_db_string(config)
477
- sh "isql -i #{filename} #{db_string}"
478
- else
479
- raise "Task not supported by '#{config['adapter']}'"
480
- end
304
+ desc "Recreates the databases from the structure.sql file"
305
+ task :load => [:environment, :load_config, :check_protected_environments] do
306
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:sql, ENV['SCHEMA'])
481
307
  end
482
308
 
483
309
  task :load_if_sql => ['db:create', :environment] do
@@ -487,8 +313,15 @@ db_namespace = namespace :db do
487
313
 
488
314
  namespace :test do
489
315
 
316
+ task :deprecated do
317
+ Rake.application.top_level_tasks.grep(/^db:test:/).each do |task|
318
+ $stderr.puts "WARNING: #{task} is deprecated. The Rails test helper now maintains " \
319
+ "your test schema automatically, see the release notes for details."
320
+ end
321
+ end
322
+
490
323
  # desc "Recreate the test database from the current schema"
491
- task :load => 'db:test:purge' do
324
+ task :load => %w(db:test:purge) do
492
325
  case ActiveRecord::Base.schema_format
493
326
  when :ruby
494
327
  db_namespace["test:load_schema"].invoke
@@ -497,93 +330,61 @@ db_namespace = namespace :db do
497
330
  end
498
331
  end
499
332
 
500
- # desc "Recreate the test database from an existent structure.sql file"
501
- task :load_structure => 'db:test:purge' do
333
+ # desc "Recreate the test database from an existent schema.rb file"
334
+ task :load_schema => %w(db:test:purge) do
502
335
  begin
503
- current_config(:config => ActiveRecord::Base.configurations['test'])
504
- db_namespace["structure:load"].invoke
336
+ should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
337
+ ActiveRecord::Schema.verbose = false
338
+ ActiveRecord::Tasks::DatabaseTasks.load_schema ActiveRecord::Base.configurations['test'], :ruby, ENV['SCHEMA']
505
339
  ensure
506
- current_config(:config => nil)
340
+ if should_reconnect
341
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[ActiveRecord::Tasks::DatabaseTasks.env])
342
+ end
507
343
  end
508
344
  end
509
345
 
510
- # desc "Recreate the test database from an existent schema.rb file"
511
- task :load_schema => 'db:test:purge' do
512
- ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])
513
- ActiveRecord::Schema.verbose = false
514
- db_namespace["schema:load"].invoke
346
+ # desc "Recreate the test database from an existent structure.sql file"
347
+ task :load_structure => %w(db:test:purge) do
348
+ ActiveRecord::Tasks::DatabaseTasks.load_schema ActiveRecord::Base.configurations['test'], :sql, ENV['SCHEMA']
349
+ end
350
+
351
+ # desc "Recreate the test database from a fresh schema"
352
+ task :clone => %w(db:test:deprecated environment) do
353
+ case ActiveRecord::Base.schema_format
354
+ when :ruby
355
+ db_namespace["test:clone_schema"].invoke
356
+ when :sql
357
+ db_namespace["test:clone_structure"].invoke
358
+ end
515
359
  end
516
360
 
517
361
  # desc "Recreate the test database from a fresh schema.rb file"
518
- task :clone => %w(db:schema:dump db:test:load_schema)
362
+ task :clone_schema => %w(db:test:deprecated db:schema:dump db:test:load_schema)
519
363
 
520
364
  # desc "Recreate the test database from a fresh structure.sql file"
521
- task :clone_structure => [ "db:structure:dump", "db:test:load_structure" ]
365
+ task :clone_structure => %w(db:test:deprecated db:structure:dump db:test:load_structure)
522
366
 
523
367
  # desc "Empty the test database"
524
- task :purge => [:environment, :load_config] do
525
- abcs = ActiveRecord::Base.configurations
526
- case abcs['test']['adapter']
527
- when /mysql/
528
- ActiveRecord::Base.establish_connection(:test)
529
- ActiveRecord::Base.connection.recreate_database(abcs['test']['database'], mysql_creation_options(abcs['test']))
530
- when /postgresql/
531
- ActiveRecord::Base.clear_active_connections!
532
- drop_database(abcs['test'])
533
- create_database(abcs['test'])
534
- when /sqlite/
535
- dbfile = abcs['test']['database']
536
- File.delete(dbfile) if File.exist?(dbfile)
537
- when 'sqlserver'
538
- test = abcs.deep_dup['test']
539
- test_database = test['database']
540
- test['database'] = 'master'
541
- ActiveRecord::Base.establish_connection(test)
542
- ActiveRecord::Base.connection.recreate_database!(test_database)
543
- when "oci", "oracle"
544
- ActiveRecord::Base.establish_connection(:test)
545
- ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl|
546
- ActiveRecord::Base.connection.execute(ddl)
547
- end
548
- when 'firebird'
549
- ActiveRecord::Base.establish_connection(:test)
550
- ActiveRecord::Base.connection.recreate_database!
551
- else
552
- raise "Task not supported by '#{abcs['test']['adapter']}'"
553
- end
368
+ task :purge => %w(environment load_config check_protected_environments) do
369
+ ActiveRecord::Tasks::DatabaseTasks.purge ActiveRecord::Base.configurations['test']
554
370
  end
555
371
 
556
- # desc 'Check for pending migrations and load the test schema'
557
- task :prepare => 'db:abort_if_pending_migrations' do
372
+ # desc 'Load the test schema'
373
+ task :prepare => %w(environment load_config) do
558
374
  unless ActiveRecord::Base.configurations.blank?
559
- db_namespace[{ :sql => 'test:clone_structure', :ruby => 'test:load' }[ActiveRecord::Base.schema_format]].invoke
375
+ db_namespace['test:load'].invoke
560
376
  end
561
377
  end
562
378
  end
563
-
564
- namespace :sessions do
565
- # desc "Creates a sessions migration for use with ActiveRecord::SessionStore"
566
- task :create => [:environment, :load_config] do
567
- raise 'Task unavailable to this database (no migration support)' unless ActiveRecord::Base.connection.supports_migrations?
568
- Rails.application.load_generators
569
- require 'rails/generators/rails/session_migration/session_migration_generator'
570
- Rails::Generators::SessionMigrationGenerator.start [ ENV['MIGRATION'] || 'add_sessions_table' ]
571
- end
572
-
573
- # desc "Clear the sessions table"
574
- task :clear => [:environment, :load_config] do
575
- ActiveRecord::Base.connection.execute "DELETE FROM #{session_table_name}"
576
- end
577
- end
578
379
  end
579
380
 
580
381
  namespace :railties do
581
382
  namespace :install do
582
- # desc "Copies missing migrations from Railties (e.g. plugins, engines). You can specify Railties to use with FROM=railtie1,railtie2"
383
+ # desc "Copies missing migrations from Railties (e.g. engines). You can specify Railties to use with FROM=railtie1,railtie2"
583
384
  task :migrations => :'db:load_config' do
584
- to_load = ENV['FROM'].blank? ? :all : ENV['FROM'].split(",").map {|n| n.strip }
585
- railties = ActiveSupport::OrderedHash.new
586
- Rails.application.railties.all do |railtie|
385
+ to_load = ENV['FROM'].blank? ? :all : ENV['FROM'].split(",").map(&:strip)
386
+ railties = {}
387
+ Rails.application.migration_railties.each do |railtie|
587
388
  next unless to_load == :all || to_load.include?(railtie.railtie_name)
588
389
 
589
390
  if railtie.respond_to?(:paths) && (path = railtie.paths['db/migrate'].first)
@@ -595,65 +396,12 @@ namespace :railties do
595
396
  puts "NOTE: Migration #{migration.basename} from #{name} has been skipped. Migration with the same name already exists."
596
397
  end
597
398
 
598
- on_copy = Proc.new do |name, migration, old_path|
399
+ on_copy = Proc.new do |name, migration|
599
400
  puts "Copied migration #{migration.basename} from #{name}"
600
401
  end
601
402
 
602
- ActiveRecord::Migration.copy(ActiveRecord::Migrator.migrations_paths.first, railties,
403
+ ActiveRecord::Migration.copy(ActiveRecord::Tasks::DatabaseTasks.migrations_paths.first, railties,
603
404
  :on_skip => on_skip, :on_copy => on_copy)
604
405
  end
605
406
  end
606
407
  end
607
-
608
- task 'test:prepare' => 'db:test:prepare'
609
-
610
- def drop_database(config)
611
- case config['adapter']
612
- when /mysql/
613
- ActiveRecord::Base.establish_connection(config)
614
- ActiveRecord::Base.connection.drop_database config['database']
615
- when /sqlite/
616
- require 'pathname'
617
- path = Pathname.new(config['database'])
618
- file = path.absolute? ? path.to_s : File.join(Rails.root, path)
619
-
620
- FileUtils.rm(file)
621
- when /postgresql/
622
- ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
623
- ActiveRecord::Base.connection.drop_database config['database']
624
- end
625
- end
626
-
627
- def drop_database_and_rescue(config)
628
- begin
629
- drop_database(config)
630
- rescue Exception => e
631
- $stderr.puts "Couldn't drop #{config['database']} : #{e.inspect}"
632
- end
633
- end
634
-
635
- def configs_for_environment
636
- environments = [Rails.env]
637
- environments << 'test' if Rails.env.development?
638
- ActiveRecord::Base.configurations.values_at(*environments).compact.reject { |config| config['database'].blank? }
639
- end
640
-
641
- def session_table_name
642
- ActiveRecord::SessionStore::Session.table_name
643
- end
644
-
645
- def set_firebird_env(config)
646
- ENV['ISC_USER'] = config['username'].to_s if config['username']
647
- ENV['ISC_PASSWORD'] = config['password'].to_s if config['password']
648
- end
649
-
650
- def firebird_db_string(config)
651
- FireRuby::Database.db_string_for(config.symbolize_keys)
652
- end
653
-
654
- def set_psql_env(config)
655
- ENV['PGHOST'] = config['host'] if config['host']
656
- ENV['PGPORT'] = config['port'].to_s if config['port']
657
- ENV['PGPASSWORD'] = config['password'].to_s if config['password']
658
- ENV['PGUSER'] = config['username'].to_s if config['username']
659
- end