activerecord 3.2.22.4 → 4.0.13

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 (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2799 -617
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +23 -32
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/aggregations.rb +40 -34
  7. data/lib/active_record/association_relation.rb +22 -0
  8. data/lib/active_record/associations/alias_tracker.rb +4 -2
  9. data/lib/active_record/associations/association.rb +60 -46
  10. data/lib/active_record/associations/association_scope.rb +46 -40
  11. data/lib/active_record/associations/belongs_to_association.rb +17 -4
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
  13. data/lib/active_record/associations/builder/association.rb +81 -28
  14. data/lib/active_record/associations/builder/belongs_to.rb +73 -56
  15. data/lib/active_record/associations/builder/collection_association.rb +54 -40
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +23 -41
  17. data/lib/active_record/associations/builder/has_many.rb +8 -64
  18. data/lib/active_record/associations/builder/has_one.rb +13 -50
  19. data/lib/active_record/associations/builder/singular_association.rb +13 -13
  20. data/lib/active_record/associations/collection_association.rb +130 -96
  21. data/lib/active_record/associations/collection_proxy.rb +916 -63
  22. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +15 -13
  23. data/lib/active_record/associations/has_many_association.rb +35 -8
  24. data/lib/active_record/associations/has_many_through_association.rb +37 -17
  25. data/lib/active_record/associations/has_one_association.rb +42 -19
  26. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  27. data/lib/active_record/associations/join_dependency/join_association.rb +39 -22
  28. data/lib/active_record/associations/join_dependency/join_base.rb +2 -2
  29. data/lib/active_record/associations/join_dependency/join_part.rb +21 -8
  30. data/lib/active_record/associations/join_dependency.rb +30 -9
  31. data/lib/active_record/associations/join_helper.rb +1 -11
  32. data/lib/active_record/associations/preloader/association.rb +29 -33
  33. data/lib/active_record/associations/preloader/collection_association.rb +1 -1
  34. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +2 -2
  35. data/lib/active_record/associations/preloader/has_many_through.rb +6 -2
  36. data/lib/active_record/associations/preloader/has_one.rb +1 -1
  37. data/lib/active_record/associations/preloader/through_association.rb +13 -17
  38. data/lib/active_record/associations/preloader.rb +20 -43
  39. data/lib/active_record/associations/singular_association.rb +11 -11
  40. data/lib/active_record/associations/through_association.rb +3 -3
  41. data/lib/active_record/associations.rb +223 -282
  42. data/lib/active_record/attribute_assignment.rb +134 -154
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +44 -5
  44. data/lib/active_record/attribute_methods/dirty.rb +36 -29
  45. data/lib/active_record/attribute_methods/primary_key.rb +45 -31
  46. data/lib/active_record/attribute_methods/query.rb +5 -4
  47. data/lib/active_record/attribute_methods/read.rb +67 -90
  48. data/lib/active_record/attribute_methods/serialization.rb +133 -70
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +51 -45
  50. data/lib/active_record/attribute_methods/write.rb +34 -39
  51. data/lib/active_record/attribute_methods.rb +268 -108
  52. data/lib/active_record/autosave_association.rb +80 -73
  53. data/lib/active_record/base.rb +54 -451
  54. data/lib/active_record/callbacks.rb +60 -22
  55. data/lib/active_record/coders/yaml_column.rb +18 -21
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +347 -197
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +146 -138
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +25 -19
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +19 -3
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +151 -142
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +499 -217
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +208 -0
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +209 -44
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +169 -61
  67. data/lib/active_record/connection_adapters/column.rb +67 -36
  68. data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
  69. data/lib/active_record/connection_adapters/mysql2_adapter.rb +28 -29
  70. data/lib/active_record/connection_adapters/mysql_adapter.rb +200 -73
  71. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +98 -0
  72. data/lib/active_record/connection_adapters/postgresql/cast.rb +160 -0
  73. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +240 -0
  74. data/lib/active_record/connection_adapters/postgresql/oid.rb +374 -0
  75. data/lib/active_record/connection_adapters/postgresql/quoting.rb +183 -0
  76. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  77. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +508 -0
  78. data/lib/active_record/connection_adapters/postgresql_adapter.rb +544 -899
  79. data/lib/active_record/connection_adapters/schema_cache.rb +76 -16
  80. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +595 -16
  81. data/lib/active_record/connection_handling.rb +98 -0
  82. data/lib/active_record/core.rb +472 -0
  83. data/lib/active_record/counter_cache.rb +107 -108
  84. data/lib/active_record/dynamic_matchers.rb +115 -63
  85. data/lib/active_record/errors.rb +36 -18
  86. data/lib/active_record/explain.rb +15 -63
  87. data/lib/active_record/explain_registry.rb +30 -0
  88. data/lib/active_record/explain_subscriber.rb +8 -4
  89. data/lib/active_record/fixture_set/file.rb +55 -0
  90. data/lib/active_record/fixtures.rb +159 -155
  91. data/lib/active_record/inheritance.rb +93 -59
  92. data/lib/active_record/integration.rb +8 -8
  93. data/lib/active_record/locale/en.yml +8 -1
  94. data/lib/active_record/locking/optimistic.rb +39 -43
  95. data/lib/active_record/locking/pessimistic.rb +4 -4
  96. data/lib/active_record/log_subscriber.rb +19 -9
  97. data/lib/active_record/migration/command_recorder.rb +102 -33
  98. data/lib/active_record/migration/join_table.rb +15 -0
  99. data/lib/active_record/migration.rb +411 -173
  100. data/lib/active_record/model_schema.rb +81 -94
  101. data/lib/active_record/nested_attributes.rb +173 -131
  102. data/lib/active_record/null_relation.rb +67 -0
  103. data/lib/active_record/persistence.rb +254 -106
  104. data/lib/active_record/query_cache.rb +18 -36
  105. data/lib/active_record/querying.rb +19 -15
  106. data/lib/active_record/railtie.rb +113 -38
  107. data/lib/active_record/railties/console_sandbox.rb +3 -4
  108. data/lib/active_record/railties/controller_runtime.rb +4 -3
  109. data/lib/active_record/railties/databases.rake +115 -368
  110. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  111. data/lib/active_record/readonly_attributes.rb +7 -3
  112. data/lib/active_record/reflection.rb +110 -61
  113. data/lib/active_record/relation/batches.rb +29 -29
  114. data/lib/active_record/relation/calculations.rb +155 -125
  115. data/lib/active_record/relation/delegation.rb +94 -18
  116. data/lib/active_record/relation/finder_methods.rb +151 -203
  117. data/lib/active_record/relation/merger.rb +188 -0
  118. data/lib/active_record/relation/predicate_builder.rb +85 -42
  119. data/lib/active_record/relation/query_methods.rb +793 -146
  120. data/lib/active_record/relation/spawn_methods.rb +43 -150
  121. data/lib/active_record/relation.rb +293 -173
  122. data/lib/active_record/result.rb +48 -7
  123. data/lib/active_record/runtime_registry.rb +17 -0
  124. data/lib/active_record/sanitization.rb +41 -54
  125. data/lib/active_record/schema.rb +19 -12
  126. data/lib/active_record/schema_dumper.rb +41 -41
  127. data/lib/active_record/schema_migration.rb +46 -0
  128. data/lib/active_record/scoping/default.rb +56 -52
  129. data/lib/active_record/scoping/named.rb +78 -103
  130. data/lib/active_record/scoping.rb +54 -124
  131. data/lib/active_record/serialization.rb +6 -2
  132. data/lib/active_record/serializers/xml_serializer.rb +9 -15
  133. data/lib/active_record/statement_cache.rb +26 -0
  134. data/lib/active_record/store.rb +131 -15
  135. data/lib/active_record/tasks/database_tasks.rb +204 -0
  136. data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
  137. data/lib/active_record/tasks/mysql_database_tasks.rb +144 -0
  138. data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
  139. data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
  140. data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
  141. data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
  142. data/lib/active_record/test_case.rb +67 -38
  143. data/lib/active_record/timestamp.rb +16 -11
  144. data/lib/active_record/transactions.rb +73 -51
  145. data/lib/active_record/validations/associated.rb +19 -13
  146. data/lib/active_record/validations/presence.rb +65 -0
  147. data/lib/active_record/validations/uniqueness.rb +110 -57
  148. data/lib/active_record/validations.rb +18 -17
  149. data/lib/active_record/version.rb +7 -6
  150. data/lib/active_record.rb +63 -45
  151. data/lib/rails/generators/active_record/migration/migration_generator.rb +45 -8
  152. data/lib/rails/generators/active_record/{model/templates/migration.rb → migration/templates/create_table_migration.rb} +4 -0
  153. data/lib/rails/generators/active_record/migration/templates/migration.rb +20 -15
  154. data/lib/rails/generators/active_record/model/model_generator.rb +5 -4
  155. data/lib/rails/generators/active_record/model/templates/model.rb +4 -6
  156. data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
  157. data/lib/rails/generators/active_record.rb +3 -5
  158. metadata +43 -29
  159. data/examples/associations.png +0 -0
  160. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  161. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  162. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  163. data/lib/active_record/dynamic_finder_match.rb +0 -68
  164. data/lib/active_record/dynamic_scope_match.rb +0 -23
  165. data/lib/active_record/fixtures/file.rb +0 -65
  166. data/lib/active_record/identity_map.rb +0 -162
  167. data/lib/active_record/observer.rb +0 -121
  168. data/lib/active_record/session_store.rb +0 -360
  169. data/lib/rails/generators/active_record/migration.rb +0 -15
  170. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  171. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  172. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  173. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,193 +1,42 @@
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
8
- end
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
22
- end
23
-
24
4
  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
5
+ ActiveRecord::Base.configurations = ActiveRecord::Tasks::DatabaseTasks.database_configuration || {}
6
+ ActiveRecord::Migrator.migrations_paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
33
7
  end
34
8
 
35
9
  namespace :create do
36
- # desc 'Create all the local databases defined in config/database.yml'
37
10
  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
11
+ ActiveRecord::Tasks::DatabaseTasks.create_all
54
12
  end
55
13
  end
56
14
 
57
15
  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
16
+ task :create => [:load_config] do
59
17
  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
65
- end
66
-
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
81
- end
82
- end
83
-
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
18
+ ActiveRecord::Tasks::DatabaseTasks.create_database_url
151
19
  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/
20
+ ActiveRecord::Tasks::DatabaseTasks.create_current
154
21
  end
155
22
  end
156
23
 
157
24
  namespace :drop do
158
- # desc 'Drops all the local databases defined in config/database.yml'
159
25
  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
26
+ ActiveRecord::Tasks::DatabaseTasks.drop_all
170
27
  end
171
28
  end
172
29
 
173
30
  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
31
+ task :drop => [:load_config] do
175
32
  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) }
179
- end
180
- end
181
-
182
- def local_database?(config, &block)
183
- if config['host'].in?(['127.0.0.1', 'localhost']) || config['host'].blank?
184
- yield
33
+ ActiveRecord::Tasks::DatabaseTasks.drop_database_url
185
34
  else
186
- $stderr.puts "This task only modifies local databases. #{config['database']} is on a remote host."
35
+ ActiveRecord::Tasks::DatabaseTasks.drop_current
187
36
  end
188
37
  end
189
38
 
190
- desc "Migrate the database (options: VERSION=x, VERBOSE=false)."
39
+ desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
191
40
  task :migrate => [:environment, :load_config] do
192
41
  ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
193
42
  ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, ENV["VERSION"] ? ENV["VERSION"].to_i : nil) do |migration|
@@ -246,13 +95,15 @@ db_namespace = namespace :db do
246
95
  next # means "return" for rake task
247
96
  end
248
97
  db_list = ActiveRecord::Base.connection.select_values("SELECT version FROM #{ActiveRecord::Migrator.schema_migrations_table_name}")
98
+ db_list.map! { |version| ActiveRecord::SchemaMigration.normalize_migration_number(version) }
249
99
  file_list = []
250
100
  ActiveRecord::Migrator.migrations_paths.each do |path|
251
101
  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]
102
+ # match "20091231235959_some_name.rb" and "001_some_name.rb" pattern
103
+ if match_data = /^(\d{3,})_(.+)\.rb$/.match(file)
104
+ version = ActiveRecord::SchemaMigration.normalize_migration_number(match_data[1])
105
+ status = db_list.delete(version) ? 'up' : 'down'
106
+ file_list << [status, version, match_data[2].humanize]
256
107
  end
257
108
  end
258
109
  end
@@ -292,31 +143,15 @@ db_namespace = namespace :db do
292
143
 
293
144
  # desc "Retrieves the charset for the current environment's database"
294
145
  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
146
+ puts ActiveRecord::Tasks::DatabaseTasks.charset_current
309
147
  end
310
148
 
311
149
  # desc "Retrieves the collation for the current environment's database"
312
150
  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'
151
+ begin
152
+ puts ActiveRecord::Tasks::DatabaseTasks.collation_current
153
+ rescue NoMethodError
154
+ $stderr.puts 'Sorry, your database adapter is not supported yet. Feel free to submit a patch.'
320
155
  end
321
156
  end
322
157
 
@@ -326,11 +161,11 @@ db_namespace = namespace :db do
326
161
  end
327
162
 
328
163
  # desc "Raises an error if there are pending migrations"
329
- task :abort_if_pending_migrations => [:environment, :load_config] do
330
- pending_migrations = ActiveRecord::Migrator.new(:up, ActiveRecord::Migrator.migrations_paths).pending_migrations
164
+ task :abort_if_pending_migrations => :environment do
165
+ pending_migrations = ActiveRecord::Migrator.open(ActiveRecord::Migrator.migrations_paths).pending_migrations
331
166
 
332
167
  if pending_migrations.any?
333
- puts "You have #{pending_migrations.size} pending migrations:"
168
+ puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
334
169
  pending_migrations.each do |pending_migration|
335
170
  puts ' %4d %s' % [pending_migration.version, pending_migration.name]
336
171
  end
@@ -344,7 +179,7 @@ db_namespace = namespace :db do
344
179
  desc 'Load the seed data from db/seeds.rb'
345
180
  task :seed do
346
181
  db_namespace['abort_if_pending_migrations'].invoke
347
- Rails.application.load_seed
182
+ ActiveRecord::Tasks::DatabaseTasks.load_seed
348
183
  end
349
184
 
350
185
  namespace :fixtures do
@@ -352,11 +187,19 @@ db_namespace = namespace :db do
352
187
  task :load => [:environment, :load_config] do
353
188
  require 'active_record/fixtures'
354
189
 
355
- base_dir = File.join [Rails.root, ENV['FIXTURES_PATH'] || %w{test fixtures}].flatten
190
+ base_dir = if ENV['FIXTURES_PATH']
191
+ STDERR.puts "Using FIXTURES_PATH env variable is deprecated, please use " +
192
+ "ActiveRecord::Tasks::DatabaseTasks.fixtures_path = '/path/to/fixtures' " +
193
+ "instead."
194
+ File.join [Rails.root, ENV['FIXTURES_PATH'] || %w{test fixtures}].flatten
195
+ else
196
+ ActiveRecord::Tasks::DatabaseTasks.fixtures_path
197
+ end
198
+
356
199
  fixtures_dir = File.join [base_dir, ENV['FIXTURES_DIR']].compact
357
200
 
358
201
  (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)
202
+ ActiveRecord::FixtureSet.create_fixtures(fixtures_dir, fixture_file)
360
203
  end
361
204
  end
362
205
 
@@ -367,13 +210,22 @@ db_namespace = namespace :db do
367
210
  label, id = ENV['LABEL'], ENV['ID']
368
211
  raise 'LABEL or ID required' if label.blank? && id.blank?
369
212
 
370
- puts %Q(The fixture ID for "#{label}" is #{ActiveRecord::Fixtures.identify(label)}.) if label
213
+ puts %Q(The fixture ID for "#{label}" is #{ActiveRecord::FixtureSet.identify(label)}.) if label
214
+
215
+ base_dir = if ENV['FIXTURES_PATH']
216
+ STDERR.puts "Using FIXTURES_PATH env variable is deprecated, please use " +
217
+ "ActiveRecord::Tasks::DatabaseTasks.fixtures_path = '/path/to/fixtures' " +
218
+ "instead."
219
+ File.join [Rails.root, ENV['FIXTURES_PATH'] || %w{test fixtures}].flatten
220
+ else
221
+ ActiveRecord::Tasks::DatabaseTasks.fixtures_path
222
+ end
223
+
371
224
 
372
- base_dir = ENV['FIXTURES_PATH'] ? File.join(Rails.root, ENV['FIXTURES_PATH']) : File.join(Rails.root, 'test', 'fixtures')
373
225
  Dir["#{base_dir}/**/*.yml"].each do |file|
374
226
  if data = YAML::load(ERB.new(IO.read(file)).result)
375
227
  data.keys.each do |key|
376
- key_id = ActiveRecord::Fixtures.identify(key)
228
+ key_id = ActiveRecord::FixtureSet.identify(key)
377
229
 
378
230
  if key == label || key_id == id.to_i
379
231
  puts "#{file}: #{key} (#{key_id})"
@@ -388,7 +240,7 @@ db_namespace = namespace :db do
388
240
  desc 'Create a db/schema.rb file that can be portably used against any DB supported by AR'
389
241
  task :dump => [:environment, :load_config] do
390
242
  require 'active_record/schema_dumper'
391
- filename = ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb"
243
+ filename = ENV['SCHEMA'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'schema.rb')
392
244
  File.open(filename, "w:utf-8") do |file|
393
245
  ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
394
246
  end
@@ -397,87 +249,59 @@ db_namespace = namespace :db do
397
249
 
398
250
  desc 'Load a schema.rb file into the database'
399
251
  task :load => [:environment, :load_config] do
400
- file = ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb"
401
- if File.exists?(file)
252
+ file = ENV['SCHEMA'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'schema.rb')
253
+ if File.exist?(file)
402
254
  load(file)
403
255
  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}
256
+ 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
257
  end
406
258
  end
407
259
 
408
260
  task :load_if_ruby => ['db:create', :environment] do
409
261
  db_namespace["schema:load"].invoke if ActiveRecord::Base.schema_format == :ruby
410
262
  end
263
+
264
+ namespace :cache do
265
+ desc 'Create a db/schema_cache.dump file.'
266
+ task :dump => [:environment, :load_config] do
267
+ con = ActiveRecord::Base.connection
268
+ filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.dump")
269
+
270
+ con.schema_cache.clear!
271
+ con.tables.each { |table| con.schema_cache.add(table) }
272
+ open(filename, 'wb') { |f| f.write(Marshal.dump(con.schema_cache)) }
273
+ end
274
+
275
+ desc 'Clear a db/schema_cache.dump file.'
276
+ task :clear => [:environment, :load_config] do
277
+ filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.dump")
278
+ FileUtils.rm(filename) if File.exist?(filename)
279
+ end
280
+ end
281
+
411
282
  end
412
283
 
413
284
  namespace :structure do
414
285
  desc 'Dump the database structure to db/structure.sql. Specify another file with DB_STRUCTURE=db/my_structure.sql'
415
286
  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(" ")
287
+ filename = ENV['DB_STRUCTURE'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql")
288
+ current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
289
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(current_config, filename)
290
+
291
+ if ActiveRecord::Base.connection.supports_migrations? &&
292
+ ActiveRecord::SchemaMigration.table_exists?
293
+ File.open(filename, "a") do |f|
294
+ f.puts ActiveRecord::Base.connection.dump_schema_information
427
295
  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
296
  end
447
297
  db_namespace['structure:dump'].reenable
448
298
  end
449
299
 
450
300
  # desc "Recreate the databases from the structure.sql file"
451
301
  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
302
+ filename = ENV['DB_STRUCTURE'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql")
303
+ current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
304
+ ActiveRecord::Tasks::DatabaseTasks.structure_load(current_config, filename)
481
305
  end
482
306
 
483
307
  task :load_if_sql => ['db:create', :environment] do
@@ -497,93 +321,67 @@ db_namespace = namespace :db do
497
321
  end
498
322
  end
499
323
 
324
+ # desc "Recreate the test database from an existent schema.rb file"
325
+ task :load_schema => 'db:test:purge' do
326
+ begin
327
+ should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
328
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])
329
+ ActiveRecord::Schema.verbose = false
330
+ db_namespace["schema:load"].invoke
331
+ ensure
332
+ if should_reconnect
333
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[ActiveRecord::Tasks::DatabaseTasks.env])
334
+ end
335
+ end
336
+ end
337
+
500
338
  # desc "Recreate the test database from an existent structure.sql file"
501
339
  task :load_structure => 'db:test:purge' do
502
340
  begin
503
- current_config(:config => ActiveRecord::Base.configurations['test'])
341
+ ActiveRecord::Tasks::DatabaseTasks.current_config(:config => ActiveRecord::Base.configurations['test'])
504
342
  db_namespace["structure:load"].invoke
505
343
  ensure
506
- current_config(:config => nil)
344
+ ActiveRecord::Tasks::DatabaseTasks.current_config(:config => nil)
507
345
  end
508
346
  end
509
347
 
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
348
+ # desc "Recreate the test database from a fresh schema"
349
+ task :clone => :environment do
350
+ case ActiveRecord::Base.schema_format
351
+ when :ruby
352
+ db_namespace["test:clone_schema"].invoke
353
+ when :sql
354
+ db_namespace["test:clone_structure"].invoke
355
+ end
515
356
  end
516
357
 
517
358
  # desc "Recreate the test database from a fresh schema.rb file"
518
- task :clone => %w(db:schema:dump db:test:load_schema)
359
+ task :clone_schema => ["db:schema:dump", "db:test:load_schema"]
519
360
 
520
361
  # desc "Recreate the test database from a fresh structure.sql file"
521
362
  task :clone_structure => [ "db:structure:dump", "db:test:load_structure" ]
522
363
 
523
364
  # desc "Empty the test database"
524
365
  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
366
+ ActiveRecord::Tasks::DatabaseTasks.purge ActiveRecord::Base.configurations['test']
554
367
  end
555
368
 
556
369
  # desc 'Check for pending migrations and load the test schema'
557
- task :prepare => 'db:abort_if_pending_migrations' do
370
+ task :prepare => [:environment, :load_config] do
558
371
  unless ActiveRecord::Base.configurations.blank?
559
- db_namespace[{ :sql => 'test:clone_structure', :ruby => 'test:load' }[ActiveRecord::Base.schema_format]].invoke
372
+ db_namespace['test:load'].invoke
560
373
  end
561
374
  end
562
375
  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
376
  end
579
377
 
580
378
  namespace :railties do
581
379
  namespace :install do
582
- # desc "Copies missing migrations from Railties (e.g. plugins, engines). You can specify Railties to use with FROM=railtie1,railtie2"
380
+ # desc "Copies missing migrations from Railties (e.g. engines). You can specify Railties to use with FROM=railtie1,railtie2"
583
381
  task :migrations => :'db:load_config' do
584
382
  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|
383
+ railties = {}
384
+ Rails.application.migration_railties.each do |railtie|
587
385
  next unless to_load == :all || to_load.include?(railtie.railtie_name)
588
386
 
589
387
  if railtie.respond_to?(:paths) && (path = railtie.paths['db/migrate'].first)
@@ -595,7 +393,7 @@ namespace :railties do
595
393
  puts "NOTE: Migration #{migration.basename} from #{name} has been skipped. Migration with the same name already exists."
596
394
  end
597
395
 
598
- on_copy = Proc.new do |name, migration, old_path|
396
+ on_copy = Proc.new do |name, migration|
599
397
  puts "Copied migration #{migration.basename} from #{name}"
600
398
  end
601
399
 
@@ -605,55 +403,4 @@ namespace :railties do
605
403
  end
606
404
  end
607
405
 
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
406
+ task 'test:prepare' => ['db:test:prepare', 'db:test:load', 'db:abort_if_pending_migrations']
@@ -1,6 +1,6 @@
1
1
  #FIXME Remove if ArJdbcMysql will give.
2
2
  module ArJdbcMySQL #:nodoc:
3
- class Error < StandardError
3
+ class Error < StandardError #:nodoc:
4
4
  attr_accessor :error_number, :sql_state
5
5
 
6
6
  def initialize msg