require'active_support/core_ext/string/filters'moduleActiveRecordmoduleTasks# :nodoc:classDatabaseAlreadyExists<StandardError;end# :nodoc:classDatabaseNotSupported<StandardError;end# :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 with 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 defaults or when you want to use Active Record outside of Rails# (in such case after configuring the database tasks, you can also use the rake tasks# defined in Active Record).## The possible config values are:## * +env+: current environment (like Rails.env).# * +database_configuration+: configuration of your databases (as in +config/database.yml+).# * +db_dir+: your +db+ directory.# * +fixtures_path+: a path to fixtures directory.# * +migrations_paths+: a list of paths to directories with migrations.# * +seed_loader+: an object which will load seeds, it needs to respond to the +load_seed+ method.# * +root+: a path to the root of the application.## Example usage of +DatabaseTasks+ outside Rails could look as such:## include ActiveRecord::Tasks# DatabaseTasks.database_configuration = YAML.load_file('my_database_config.yml')# DatabaseTasks.db_dir = 'db'# # other settings...## DatabaseTasks.create_current('production')moduleDatabaseTasksextendselfattr_writer:current_config,:db_dir,:migrations_paths,:fixtures_path,:root,:env,:seed_loaderattr_accessor:database_configurationLOCAL_HOSTS=['127.0.0.1','localhost']defregister_task(pattern,task)@tasks||={}@tasks[pattern]=taskendregister_task(/mysql/,ActiveRecord::Tasks::MySQLDatabaseTasks)register_task(/postgresql/,ActiveRecord::Tasks::PostgreSQLDatabaseTasks)register_task(/sqlite/,ActiveRecord::Tasks::SQLiteDatabaseTasks)defdb_dir@db_dir||=Rails.application.config.paths["db"].firstenddefmigrations_paths@migrations_paths||=Rails.application.paths['db/migrate'].to_aenddeffixtures_path@fixtures_path||=ifENV['FIXTURES_PATH']File.join(root,ENV['FIXTURES_PATH'])elseFile.join(root,'test','fixtures')endenddefroot@root||=Rails.rootenddefenv@env||=Rails.envenddefseed_loader@seed_loader||=Rails.applicationenddefcurrent_config(options={})options.reverse_merge!:env=>envifoptions.has_key?(:config)@current_config=options[:config]else@current_config||=ActiveRecord::Base.configurations[options[:env]]endenddefcreate(*arguments)configuration=arguments.firstclass_for_adapter(configuration['adapter']).new(*arguments).createrescueDatabaseAlreadyExists$stderr.puts"#{configuration['database']} already exists"rescueException=>error$stderr.putserror,*(error.backtrace)$stderr.puts"Couldn't create database for #{configuration.inspect}"enddefcreate_alleach_local_configuration{|configuration|createconfiguration}enddefcreate_current(environment=env)each_current_configuration(environment){|configuration|createconfiguration}ActiveRecord::Base.establish_connection(environment.to_sym)enddefdrop(*arguments)configuration=arguments.firstclass_for_adapter(configuration['adapter']).new(*arguments).droprescueActiveRecord::NoDatabaseError$stderr.puts"Database '#{configuration['database']}' does not exist"rescueException=>error$stderr.putserror,*(error.backtrace)$stderr.puts"Couldn't drop #{configuration['database']}"enddefdrop_alleach_local_configuration{|configuration|dropconfiguration}enddefdrop_current(environment=env)each_current_configuration(environment){|configuration|dropconfiguration}enddefmigrateverbose=ENV["VERBOSE"]?ENV["VERBOSE"]=="true":trueversion=ENV["VERSION"]?ENV["VERSION"].to_i:nilscope=ENV['SCOPE']verbose_was,Migration.verbose=Migration.verbose,verboseMigrator.migrate(Migrator.migrations_paths,version)do|migration|scope.blank?||scope==migration.scopeendensureMigration.verbose=verbose_wasenddefcharset_current(environment=env)charsetActiveRecord::Base.configurations[environment]enddefcharset(*arguments)configuration=arguments.firstclass_for_adapter(configuration['adapter']).new(*arguments).charsetenddefcollation_current(environment=env)collationActiveRecord::Base.configurations[environment]enddefcollation(*arguments)configuration=arguments.firstclass_for_adapter(configuration['adapter']).new(*arguments).collationenddefpurge(configuration)class_for_adapter(configuration['adapter']).new(configuration).purgeenddefpurge_alleach_local_configuration{|configuration|purgeconfiguration}enddefpurge_current(environment=env)each_current_configuration(environment){|configuration|purgeconfiguration}ActiveRecord::Base.establish_connection(environment.to_sym)enddefstructure_dump(*arguments)configuration=arguments.firstfilename=arguments.delete_at1class_for_adapter(configuration['adapter']).new(*arguments).structure_dump(filename)enddefstructure_load(*arguments)configuration=arguments.firstfilename=arguments.delete_at1class_for_adapter(configuration['adapter']).new(*arguments).structure_load(filename)enddefload_schema(format=ActiveRecord::Base.schema_format,file=nil)ActiveSupport::Deprecation.warn(<<-MSG.squish)
This method will act on a specific connection in the future.
To act on the current connection, use `load_schema_current` instead.
MSGload_schema_current(format,file)enddefschema_file(format=ActiveSupport::Base.schema_format)caseformatwhen:rubyFile.join(db_dir,"schema.rb")when:sqlFile.join(db_dir,"structure.sql")endend# This method is the successor of +load_schema+. We should rename it# after +load_schema+ went through a deprecation cycle. (Rails > 4.2)defload_schema_for(configuration,format=ActiveRecord::Base.schema_format,file=nil)# :nodoc:file||=schema_file(format)caseformatwhen:rubycheck_schema_file(file)purge(configuration)ActiveRecord::Base.establish_connection(configuration)load(file)when:sqlcheck_schema_file(file)purge(configuration)structure_load(configuration,file)elseraiseArgumentError,"unknown format #{format.inspect}"endenddefload_schema_current_if_exists(format=ActiveRecord::Base.schema_format,file=nil,environment=env)ifFile.exist?(file||schema_file(format))load_schema_current(format,file,environment)endenddefload_schema_current(format=ActiveRecord::Base.schema_format,file=nil,environment=env)each_current_configuration(environment){|configuration|load_schema_forconfiguration,format,file}ActiveRecord::Base.establish_connection(environment.to_sym)enddefcheck_schema_file(filename)unlessFile.exist?(filename)message=%{#{filename} doesn't exist yet. Run `rake db:migrate` to create it, then try again.}message<<%{ If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded.}ifdefined?(::Rails)Kernel.abortmessageendenddefload_seedifseed_loaderseed_loader.load_seedelseraise"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"endendprivatedefclass_for_adapter(adapter)key=@tasks.keys.detect{|pattern|adapter[pattern]}unlesskeyraiseDatabaseNotSupported,"Rake tasks not supported by '#{adapter}' adapter"end@tasks[key]enddefeach_current_configuration(environment)environments=[environment]# add test environment only if no RAILS_ENV was specified.environments<<'test'ifenvironment=='development'&&ENV['RAILS_ENV'].nil?configurations=ActiveRecord::Base.configurations.values_at(*environments)configurations.compact.eachdo|configuration|yieldconfigurationunlessconfiguration['database'].blank?endenddefeach_local_configurationActiveRecord::Base.configurations.each_valuedo|configuration|nextunlessconfiguration['database']iflocal_database?(configuration)yieldconfigurationelse$stderr.puts"This task only modifies local databases. #{configuration['database']} is on a remote host."endendenddeflocal_database?(configuration)configuration['host'].blank?||LOCAL_HOSTS.include?(configuration['host'])endendendend