diff options
-rw-r--r-- | activerecord/CHANGELOG.md | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/railtie.rb | 14 | ||||
-rw-r--r-- | activerecord/lib/active_record/railties/databases.rake | 45 | ||||
-rw-r--r-- | activerecord/lib/active_record/tasks/database_tasks.rb | 55 |
4 files changed, 92 insertions, 24 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index a171ee8293..b9acf6847c 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -7,6 +7,8 @@ *Dan Erikson & kennyj* +* Allow to use databases.rake tasks without having Rails.application *Piotr Sarnacki* + * Fix for a regression bug in which counter cache columns were not being updated when record was pushed into a has_many association. For example: diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index 99117b74c5..e36888d4a8 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -36,6 +36,20 @@ module ActiveRecord rake_tasks do require "active_record/base" + + ActiveRecord::Tasks::DatabaseTasks.env = Rails.env + ActiveRecord::Tasks::DatabaseTasks.db_dir = Rails.application.config.paths["db"].first + ActiveRecord::Tasks::DatabaseTasks.seed_loader = Rails.application + ActiveRecord::Tasks::DatabaseTasks.database_configuration = Rails.application.config.database_configuration + ActiveRecord::Tasks::DatabaseTasks.migrations_paths = Rails.application.paths['db/migrate'].to_a + ActiveRecord::Tasks::DatabaseTasks.fixtures_path = File.join Rails.root, 'test', 'fixtures' + + if defined?(ENGINE_PATH) && engine = Rails::Engine.find(ENGINE_PATH) + if engine.paths['db/migrate'].existent + ActiveRecord::Tasks::DatabaseTasks.migrations_paths += engine.paths['db/migrate'].to_a + end + end + load "active_record/railties/databases.rake" end diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index fb1bab6dcc..bb9e390c8f 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -2,14 +2,8 @@ require 'active_record' db_namespace = namespace :db do task :load_config do - ActiveRecord::Base.configurations = Rails.application.config.database_configuration || {} - ActiveRecord::Migrator.migrations_paths = Rails.application.paths['db/migrate'].to_a - - if defined?(ENGINE_PATH) && engine = Rails::Engine.find(ENGINE_PATH) - if engine.paths['db/migrate'].existent - ActiveRecord::Migrator.migrations_paths += engine.paths['db/migrate'].to_a - end - end + ActiveRecord::Base.configurations = ActiveRecord::Tasks::DatabaseTasks.database_configuration || {} + ActiveRecord::Migrator.migrations_paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths end namespace :create do @@ -184,7 +178,7 @@ db_namespace = namespace :db do desc 'Load the seed data from db/seeds.rb' task :seed do db_namespace['abort_if_pending_migrations'].invoke - Rails.application.load_seed + ActiveRecord::Tasks::DatabaseTasks.load_seed end namespace :fixtures do @@ -192,7 +186,15 @@ db_namespace = namespace :db do task :load => [:environment, :load_config] do require 'active_record/fixtures' - base_dir = File.join [Rails.root, ENV['FIXTURES_PATH'] || %w{test fixtures}].flatten + base_dir = if ENV['FIXTURES_PATH'] + STDERR.puts "Using FIXTURES_PATH env variable is deprecated, please use " + + "ActiveRecord::Tasks::DatabaseTasks.fixtures_path = '/path/to/fixtures' " + + "instead." + File.join [Rails.root, ENV['FIXTURES_PATH'] || %w{test fixtures}].flatten + else + ActiveRecord::Tasks::DatabaseTasks.fixtures_path + end + fixtures_dir = File.join [base_dir, ENV['FIXTURES_DIR']].compact (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir["#{fixtures_dir}/**/*.yml"].map {|f| f[(fixtures_dir.size + 1)..-5] }).each do |fixture_file| @@ -209,7 +211,16 @@ db_namespace = namespace :db do puts %Q(The fixture ID for "#{label}" is #{ActiveRecord::FixtureSet.identify(label)}.) if label - base_dir = ENV['FIXTURES_PATH'] ? File.join(Rails.root, ENV['FIXTURES_PATH']) : File.join(Rails.root, 'test', 'fixtures') + base_dir = if ENV['FIXTURES_PATH'] + STDERR.puts "Using FIXTURES_PATH env variable is deprecated, please use " + + "ActiveRecord::Tasks::DatabaseTasks.fixtures_path = '/path/to/fixtures' " + + "instead." + File.join [Rails.root, ENV['FIXTURES_PATH'] || %w{test fixtures}].flatten + else + ActiveRecord::Tasks::DatabaseTasks.fixtures_path + end + + Dir["#{base_dir}/**/*.yml"].each do |file| if data = YAML::load(ERB.new(IO.read(file)).result) data.keys.each do |key| @@ -228,7 +239,7 @@ db_namespace = namespace :db do desc 'Create a db/schema.rb file that can be portably used against any DB supported by AR' task :dump => [:environment, :load_config] do require 'active_record/schema_dumper' - filename = ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb" + filename = ENV['SCHEMA'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'schema.rb') File.open(filename, "w:utf-8") do |file| ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file) end @@ -237,7 +248,7 @@ db_namespace = namespace :db do desc 'Load a schema.rb file into the database' task :load => [:environment, :load_config] do - file = ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb" + file = ENV['SCHEMA'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'schema.rb') if File.exists?(file) load(file) else @@ -253,7 +264,7 @@ db_namespace = namespace :db do desc 'Create a db/schema_cache.dump file.' task :dump => [:environment, :load_config] do con = ActiveRecord::Base.connection - filename = File.join(Rails.application.config.paths["db"].first, "schema_cache.dump") + filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.dump") con.schema_cache.clear! con.tables.each { |table| con.schema_cache.add(table) } @@ -262,7 +273,7 @@ db_namespace = namespace :db do desc 'Clear a db/schema_cache.dump file.' task :clear => [:environment, :load_config] do - filename = File.join(Rails.application.config.paths["db"].first, "schema_cache.dump") + filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.dump") FileUtils.rm(filename) if File.exists?(filename) end end @@ -272,7 +283,7 @@ db_namespace = namespace :db do namespace :structure do desc 'Dump the database structure to db/structure.sql. Specify another file with DB_STRUCTURE=db/my_structure.sql' task :dump => [:environment, :load_config] do - filename = ENV['DB_STRUCTURE'] || File.join(Rails.root, "db", "structure.sql") + filename = ENV['DB_STRUCTURE'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql") current_config = ActiveRecord::Tasks::DatabaseTasks.current_config ActiveRecord::Tasks::DatabaseTasks.structure_dump(current_config, filename) @@ -286,7 +297,7 @@ db_namespace = namespace :db do # desc "Recreate the databases from the structure.sql file" task :load => [:environment, :load_config] do - filename = ENV['DB_STRUCTURE'] || File.join(Rails.root, "db", "structure.sql") + filename = ENV['DB_STRUCTURE'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql") current_config = ActiveRecord::Tasks::DatabaseTasks.current_config ActiveRecord::Tasks::DatabaseTasks.structure_load(current_config, filename) end diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index 36133bab4c..019fb62152 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -3,10 +3,41 @@ module ActiveRecord class DatabaseAlreadyExists < StandardError; end # :nodoc: class DatabaseNotSupported < StandardError; end # :nodoc: - module DatabaseTasks # :nodoc: + # <tt>ActiveRecord::Tasks::DatabaseTasks</tt> is a utility class, which encapsulates + # logic behind common tasks used to manage database and migrations. + # + # The tasks defined here are used in rake tasks provided by Active Record. + # + # In order to use DatabaseTasks, a few config values need to be set. All the needed + # config values are set by rails already, so it's necessary to do it only if you + # want to change the default or when you want to use Active Record outside of Rails + # (in such case after cofniguring database tasks, you can also use rake tasks defined in + # Active Record) + # + # + # The possible config values are the following: + # + # * env: current environment + # * db_dir: your 'db' directory + # * seed_loader: an object which will load seeds, it needs to respond to `load_seed` method + # * database_configuration: configuration of your databases (as in config/database.yml) + # * migrations_paths: a list of paths to directories with migrations + # * fixtures_path: a path to fixtures directory + # + # Example usage of DatabaseTasks outside Rails could look as such: + # + # include ActiveRecord::Tasks + # DatabaseTasks.database_configuration = YAML.load(File.read('my_database_config.yml')) + # DatabaseTasks.db_dir = 'db' + # # other settings... + # + # DatabaseTasks.create_current('production') + module DatabaseTasks extend self attr_writer :current_config + attr_accessor :database_configuration, :migrations_paths, :seed_loader, :db_dir, + :fixtures_path, :env LOCAL_HOSTS = ['127.0.0.1', 'localhost'] @@ -24,7 +55,7 @@ module ActiveRecord register_task(/(oci|oracle)/, ActiveRecord::Tasks::OracleDatabaseTasks) def current_config(options = {}) - options.reverse_merge! :env => Rails.env + options.reverse_merge! :env => env if options.has_key?(:config) @current_config = options[:config] else @@ -50,7 +81,7 @@ module ActiveRecord each_local_configuration { |configuration| create configuration } end - def create_current(environment = Rails.env) + def create_current(environment = env) each_current_configuration(environment) { |configuration| create configuration } @@ -73,7 +104,7 @@ module ActiveRecord each_local_configuration { |configuration| drop configuration } end - def drop_current(environment = Rails.env) + def drop_current(environment = env) each_current_configuration(environment) { |configuration| drop configuration } @@ -83,7 +114,7 @@ module ActiveRecord drop database_url_config end - def charset_current(environment = Rails.env) + def charset_current(environment = env) charset ActiveRecord::Base.configurations[environment] end @@ -92,7 +123,7 @@ module ActiveRecord class_for_adapter(configuration['adapter']).new(*arguments).charset end - def collation_current(environment = Rails.env) + def collation_current(environment = env) collation ActiveRecord::Base.configurations[environment] end @@ -117,6 +148,16 @@ module ActiveRecord class_for_adapter(configuration['adapter']).new(*arguments).structure_load(filename) end + def load_seed + if seed_loader + seed_loader.load_seed + else + raise "You tried to load seed data, but no seed loader is specified. Please specify seed " + + "loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n" + + "Seed loader should respond to load_seed method" + end + end + private def database_url_config @@ -134,7 +175,7 @@ module ActiveRecord def each_current_configuration(environment) environments = [environment] - environments << 'test' if environment.development? + environments << 'test' if environment == 'development' configurations = ActiveRecord::Base.configurations.values_at(*environments) configurations.compact.each do |configuration| |