跳至內容 跳至搜尋

Active Record DatabaseTasks

ActiveRecord::Tasks::DatabaseTasks 是個工具類別,封裝了用於管理資料庫和遷移的常見任務背後的邏輯。

這裡定義的任務與 Active Record 提供的 Rails 指令一起使用。

為了使用 DatabaseTasks,需要設定一些設定值。所有需要的設定值都已經由 Rails 設定好了,所以只有當您想要變更預設值或是在 Rails 外部使用 Active Record 時才需要這麼做(在這種情況下,在設定資料庫任務後,您也可以使用 Active Record 中定義的 rake 任務)。

可能的設定值為

  • env:目前的環境(例如 Rails.env)。

  • database_configuration:資料庫的設定(如 config/database.yml)。

  • db_dir:您的 db 目錄。

  • fixtures_path:固定裝置目錄的路徑。

  • migrations_paths:包含遷移目錄的路徑清單。

  • seed_loader:將載入種子的物件,它需要回應 load_seed 方法。

  • root:應用程式根目錄的路徑。

在 Rails 外部使用 DatabaseTasks 的範例用法如下

include ActiveRecord::Tasks
DatabaseTasks.database_configuration = YAML.load_file('my_database_config.yml')
DatabaseTasks.db_dir = 'db'
# other settings...

DatabaseTasks.create_current('production')
方法
C
D
E
F
L
M
N
P
R
S
T

常數

LOCAL_HOSTS = ["127.0.0.1", "localhost"]
 

屬性

[RW] database_configuration
[W] db_dir
[W] env
[W] fixtures_path
[W] migrations_paths
[W] root
[W] seed_loader

類別公開方法

structure_dump_flags

呼叫 db:schema:dump 時傳遞給資料庫 CLI 工具 (mysqldump/pg_dump) 的額外旗標。可以使用字串/陣列 (一般情況) 或雜湊 (當您使用多個配接器時)。範例

ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
  mysql2: ['--no-defaults', '--skip-add-drop-table'],
  postgres: '--no-tablespaces'
}
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 50
mattr_accessor :structure_dump_flags, instance_accessor: false

structure_load_flags

呼叫 db:schema:load 時傳遞給資料庫 CLI 工具的額外旗標。可以使用字串/陣列 (一般情況) 或雜湊 (當您使用多個配接器時)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 56
mattr_accessor :structure_load_flags, instance_accessor: false

實例公開方法

cache_dump_filename(db_config_name, schema_cache_path: nil)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 440
def cache_dump_filename(db_config_name, schema_cache_path: nil)
  filename = if ActiveRecord::Base.configurations.primary?(db_config_name)
    "schema_cache.yml"
  else
    "#{db_config_name}_schema_cache.yml"
  end

  schema_cache_path || ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
end

charset(configuration, *arguments)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 305
def charset(configuration, *arguments)
  db_config = resolve_configuration(configuration)
  database_adapter_for(db_config, *arguments).charset
end

charset_current(env_name = env, db_name = name)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 300
def charset_current(env_name = env, db_name = name)
  db_config = configs_for(env_name: env_name, name: db_name)
  charset(db_config)
end

check_protected_environments!(environment = env)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 65
def check_protected_environments!(environment = env)
  return if ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"]

  configs_for(env_name: environment).each do |db_config|
    check_current_protected_environment!(db_config)
  end
end

check_schema_file(filename)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 458
def check_schema_file(filename)
  unless File.exist?(filename)
    message = +%{#{filename} doesn't exist yet. Run `bin/rails 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.} if defined?(::Rails.root)
    Kernel.abort message
  end
end

check_target_version()

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 290
def check_target_version
  if target_version && !Migration.valid_version_format?(ENV["VERSION"])
    raise "Invalid format of target version: `VERSION=#{ENV['VERSION']}`"
  end
end

clear_schema_cache(filename)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 484
def clear_schema_cache(filename)
  FileUtils.rm_f filename, verbose: false
end

collation(configuration, *arguments)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 315
def collation(configuration, *arguments)
  db_config = resolve_configuration(configuration)
  database_adapter_for(db_config, *arguments).collation
end

collation_current(env_name = env, db_name = name)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 310
def collation_current(env_name = env, db_name = name)
  db_config = configs_for(env_name: env_name, name: db_name)
  collation(db_config)
end

create(configuration, *arguments)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 115
def create(configuration, *arguments)
  db_config = resolve_configuration(configuration)
  database_adapter_for(db_config, *arguments).create
  $stdout.puts "Created database '#{db_config.database}'" if verbose?
rescue DatabaseAlreadyExists
  $stderr.puts "Database '#{db_config.database}' already exists" if verbose?
rescue Exception => error
  $stderr.puts error
  $stderr.puts "Couldn't create '#{db_config.database}' database. Please check your configuration."
  raise
end

create_all()

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 127
def create_all
  each_local_configuration do |db_config|
    with_temporary_connection(db_config) do
      create(db_config)
    end
  end
end

create_current(environment = env, name = nil)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 170
def create_current(environment = env, name = nil)
  each_current_configuration(environment, name) { |db_config| create(db_config) }

  migration_class.establish_connection(environment.to_sym)
end

db_dir()

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 83
def db_dir
  @db_dir ||= Rails.application.config.paths["db"].first
end

drop(configuration, *arguments)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 204
def drop(configuration, *arguments)
  db_config = resolve_configuration(configuration)
  database_adapter_for(db_config, *arguments).drop
  $stdout.puts "Dropped database '#{db_config.database}'" if verbose?
rescue ActiveRecord::NoDatabaseError
  $stderr.puts "Database '#{db_config.database}' does not exist"
rescue Exception => error
  $stderr.puts error
  $stderr.puts "Couldn't drop database '#{db_config.database}'"
  raise
end

drop_all()

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 216
def drop_all
  each_local_configuration { |db_config| drop(db_config) }
end

drop_current(environment = env)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 220
def drop_current(environment = env)
  each_current_configuration(environment) { |db_config| drop(db_config) }
end

dump_schema_cache(conn, filename)

將連線的 Schema 快取以 YAML 格式傾印到檔案中

範例

ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, "tmp/schema_dump.yaml")
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 480
def dump_schema_cache(conn, filename)
  conn.schema_cache.dump_to(filename)
end

env()

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 103
def env
  @env ||= Rails.env
end

fixtures_path()

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 91
def fixtures_path
  @fixtures_path ||= if ENV["FIXTURES_PATH"]
    File.join(root, ENV["FIXTURES_PATH"])
  else
    File.join(root, "test", "fixtures")
  end
end

load_schema_current(format = ActiveRecord.schema_format, file = nil, environment = env)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 450
def load_schema_current(format = ActiveRecord.schema_format, file = nil, environment = env)
  each_current_configuration(environment) do |db_config|
    with_temporary_connection(db_config) do
      load_schema(db_config, format, file)
    end
  end
end

load_seed()

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 466
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

migrate(version = nil)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 237
def migrate(version = nil)
  scope = ENV["SCOPE"]
  verbose_was, Migration.verbose = Migration.verbose, verbose?

  check_target_version

  migration_connection.migration_context.migrate(target_version) do |migration|
    if version.blank?
      scope.blank? || scope == migration.scope
    else
      migration.version == version
    end
  end.tap do |migrations_ran|
    Migration.write("No migrations ran. (using #{scope} scope)") if scope.present? && migrations_ran.empty?
  end

  migration_connection.schema_cache.clear!
ensure
  Migration.verbose = verbose_was
end

migrate_status()

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 275
def migrate_status
  unless migration_connection.schema_migration.table_exists?
    Kernel.abort "Schema migrations table does not exist yet."
  end

  # output
  puts "\ndatabase: #{migration_connection.pool.db_config.database}\n\n"
  puts "#{'Status'.center(8)}  #{'Migration ID'.ljust(14)}  Migration Name"
  puts "-" * 50
  migration_connection.migration_context.migrations_status.each do |status, version, name|
    puts "#{status.center(8)}  #{version.ljust(14)}  #{name}"
  end
  puts
end

migrations_paths()

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 87
def migrations_paths
  @migrations_paths ||= Rails.application.paths["db/migrate"].to_a
end

name()

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 107
def name
  @name ||= "primary"
end

prepare_all()

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 176
def prepare_all
  seed = false

  each_current_configuration(env) do |db_config|
    with_temporary_pool(db_config) do
      begin
        database_initialized = migration_connection.schema_migration.table_exists?
      rescue ActiveRecord::NoDatabaseError
        create(db_config)
        retry
      end

      unless database_initialized
        if File.exist?(schema_dump_path(db_config))
          load_schema(db_config, ActiveRecord.schema_format, nil)
        end

        seed = true
      end

      migrate
      dump_schema(db_config) if ActiveRecord.dump_schema_after_migration
    end
  end

  load_seed if seed
end

purge(configuration)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 320
def purge(configuration)
  db_config = resolve_configuration(configuration)
  database_adapter_for(db_config).purge
end

purge_all()

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 325
def purge_all
  each_local_configuration { |db_config| purge(db_config) }
end

purge_current(environment = env)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 329
def purge_current(environment = env)
  each_current_configuration(environment) { |db_config| purge(db_config) }

  migration_class.establish_connection(environment.to_sym)
end

register_task(pattern, task)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 73
def register_task(pattern, task)
  @tasks ||= {}
  @tasks[pattern] = task
end

root()

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 99
def root
  @root ||= Rails.root
end

schema_dump_path(db_config, format = ActiveRecord.schema_format)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 427
def schema_dump_path(db_config, format = ActiveRecord.schema_format)
  return ENV["SCHEMA"] if ENV["SCHEMA"]

  filename = db_config.schema_dump(format)
  return unless filename

  if File.dirname(filename) == ActiveRecord::Tasks::DatabaseTasks.db_dir
    filename
  else
    File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
  end
end

schema_up_to_date?(configuration, format = ActiveRecord.schema_format, file = nil)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 370
def schema_up_to_date?(configuration, format = ActiveRecord.schema_format, file = nil)
  db_config = resolve_configuration(configuration)

  file ||= schema_dump_path(db_config)

  return true unless file && File.exist?(file)

  with_temporary_connection(db_config) do |connection|
    return false unless connection.internal_metadata.enabled?
    return false unless connection.internal_metadata.table_exists?

    connection.internal_metadata[:schema_sha1] == schema_sha1(file)
  end
end

seed_loader()

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 111
def seed_loader
  @seed_loader ||= Rails.application
end

structure_dump(configuration, *arguments)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 335
def structure_dump(configuration, *arguments)
  db_config = resolve_configuration(configuration)
  filename = arguments.delete_at(0)
  flags = structure_dump_flags_for(db_config.adapter)
  database_adapter_for(db_config, *arguments).structure_dump(filename, flags)
end

structure_load(configuration, *arguments)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 342
def structure_load(configuration, *arguments)
  db_config = resolve_configuration(configuration)
  filename = arguments.delete_at(0)
  flags = structure_load_flags_for(db_config.adapter)
  database_adapter_for(db_config, *arguments).structure_load(filename, flags)
end

target_version()

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 296
def target_version
  ENV["VERSION"].to_i if ENV["VERSION"] && !ENV["VERSION"].empty?
end

truncate_all(environment = env)

# File activerecord/lib/active_record/tasks/database_tasks.rb, line 231
def truncate_all(environment = env)
  configs_for(env_name: environment).each do |db_config|
    truncate_tables(db_config)
  end
end