From d1d7c86d0c8dcb7e75a87644b330c4e9e7d6c1c1 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 24 Apr 2013 15:37:55 +0200 Subject: Don't require having Rails.application to run database tasks --- activerecord/CHANGELOG.md | 4 ++++ activerecord/lib/active_record/railtie.rb | 12 +++++++++++ .../lib/active_record/railties/databases.rake | 24 ++++++++-------------- .../lib/active_record/tasks/database_tasks.rb | 11 ++++++++++ 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 66c73bfe0f..16c25eeecd 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,7 @@ +## Rails 4.1.0 (unreleased) ## + +* Allow to use databases.rake tasks without having Rails.application *Piotr Sarnacki* + ## Rails 4.0.0 (unreleased) ## * Fix for a regression bug in which counter cache columns were not being updated diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index 99117b74c5..f3f1663f76 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -36,6 +36,18 @@ module ActiveRecord rake_tasks do require "active_record/base" + + 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 + + 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..6100a38d57 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 @@ -228,7 +222,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 +231,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 +247,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 +256,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 +266,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 +280,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..9588d6c6c6 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -7,6 +7,7 @@ module ActiveRecord extend self attr_writer :current_config + attr_accessor :database_configuration, :migrations_paths, :seed_loader, :db_dir LOCAL_HOSTS = ['127.0.0.1', 'localhost'] @@ -117,6 +118,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 -- cgit v1.2.3 From 4522761c0a51f9d024b5418ecd8655664b96496d Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 24 Apr 2013 20:38:20 +0200 Subject: Use DatabaseTasks.fixtures_path instead of FIXTURES_PATH in db.rake This will allow to set fixtures path in global config easier, it should be not needed to use FIXTURES_PATH every time user wants to load fixtures. --- activerecord/lib/active_record/railtie.rb | 1 + .../lib/active_record/railties/databases.rake | 21 +++++++++++++++++++-- .../lib/active_record/tasks/database_tasks.rb | 3 ++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index f3f1663f76..ed3df1661a 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -41,6 +41,7 @@ module ActiveRecord 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 diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index 6100a38d57..bb9e390c8f 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -186,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| @@ -203,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| diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index 9588d6c6c6..7d1462a271 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -7,7 +7,8 @@ module ActiveRecord extend self attr_writer :current_config - attr_accessor :database_configuration, :migrations_paths, :seed_loader, :db_dir + attr_accessor :database_configuration, :migrations_paths, :seed_loader, :db_dir, + :fixtures_path LOCAL_HOSTS = ['127.0.0.1', 'localhost'] -- cgit v1.2.3 From 414ab0c4f42d7cb4bf9af075d38527cf5728d9bd Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 24 Apr 2013 20:54:51 +0200 Subject: Add some documentation to ActiveRecord::Tasks::DatabaseTasks This is a public class, which could be used directly in order to allow easier database management. Now it also contains settings, which will be used by databases.rake. --- .../lib/active_record/tasks/database_tasks.rb | 30 +++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index 7d1462a271..1a173a11b7 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -3,7 +3,35 @@ module ActiveRecord class DatabaseAlreadyExists < StandardError; end # :nodoc: class DatabaseNotSupported < StandardError; end # :nodoc: - module DatabaseTasks # :nodoc: + # ActiveRecord::Tasks::DatabaseTasks 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: + # + # * 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 -- cgit v1.2.3 From 20f1495af8a3461dab4c8378a2c774d694b17c51 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 24 Apr 2013 20:57:09 +0200 Subject: Don't require Rails.env in order to use AR::Tasks::DatabaseTasks --- activerecord/lib/active_record/railtie.rb | 1 + activerecord/lib/active_record/tasks/database_tasks.rb | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index ed3df1661a..e36888d4a8 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -37,6 +37,7 @@ 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 diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index 1a173a11b7..5d3f34a9b0 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -17,6 +17,7 @@ module ActiveRecord # # 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) @@ -36,7 +37,7 @@ module ActiveRecord attr_writer :current_config attr_accessor :database_configuration, :migrations_paths, :seed_loader, :db_dir, - :fixtures_path + :fixtures_path, :env LOCAL_HOSTS = ['127.0.0.1', 'localhost'] @@ -54,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 @@ -80,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 } @@ -103,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 } @@ -113,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 @@ -122,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 -- cgit v1.2.3 From b5ae43a4360b256d1dd78f55ce0c66c1470743fc Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 24 Apr 2013 21:05:43 +0200 Subject: Move CHANGELOG entry for db.rake improvements to 4.0.0 --- activerecord/CHANGELOG.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 16c25eeecd..f81836a870 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,9 +1,7 @@ -## Rails 4.1.0 (unreleased) ## +## Rails 4.0.0 (unreleased) ## * Allow to use databases.rake tasks without having Rails.application *Piotr Sarnacki* -## Rails 4.0.0 (unreleased) ## - * 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: -- cgit v1.2.3 From 1dac2edb016b7de260f16beea3b30d39e118d499 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 24 Apr 2013 21:36:28 +0200 Subject: Use env == 'development' instead of env.development? It's simpler to assume that passed env is just a string without any extensions, especially when DatabaseTasks are intended to be used also without rails. --- activerecord/lib/active_record/tasks/database_tasks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index 5d3f34a9b0..019fb62152 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -175,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| -- cgit v1.2.3