在与标准“生产”不同的数据库上使用 Rails Migration或“开发”

发布于 2024-08-04 19:34:12 字数 460 浏览 3 评论 0原文

我有一个正在运行的 Rails 项目,它在 config/database.yml 中定义了标准的 production:、:development 和 :test DB 连接

此外,我还有一个 quiz_development: 和 quiz_product: 定义指向不同的主机/db/user/password

My现在的目标是定义一个使用“quiz_#{RAILS_ENV}`”作为其数据库配置的迁移。

我尝试过(但失败了):

  • 在迁移文件中设置 ActiveRecord::Base.connection
  • 更改 Rails 中的 db:migrate 任务以在那里设置 ActiveRecord::Base.connection

问题:

如何使 rake db:migrate 使用其他的数据库定义?

谢谢, 坦率

I have a rails project running that defines the standard production:, :development and :test DB-connections in config/database.yml

In addition I have a quiz_development: and quiz_production: definition pointing to a differnet host/db/user/password

My goal now is to define a Migration that uses "quiz_#{RAILS_ENV}`" as its database configuration.

What I have tried (and failed):

  • Setting ActiveRecord::Base.connection in the Migration file
  • Changing the db:migrate task in rails to set ActiveRecord::Base.connection there

Question:

How can I make rake db:migrate use that other database definition?

Thanks,
Frank

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(20

随梦而飞# 2024-08-11 19:34:12

有一个更简单的答案。将其添加到您的迁移中:

def connection
  ActiveRecord::Base.establish_connection("quiz_#{Rails.env}").connection
end

That's for Rails 3.1。对于 Rails 2.X 或 3.0,它是一个类函数(例如 def self.connection

There's a much easier answer. Add this to your migration:

def connection
  ActiveRecord::Base.establish_connection("quiz_#{Rails.env}").connection
end

That's for Rails 3.1. For Rails 2.X or 3.0 it's a class function instead (eg def self.connection)

早茶月光 2024-08-11 19:34:12

我让它与以下代码一起使用。

class AddInProgressToRefHighLevelStatuses < ActiveRecord::Migration
  def connection
    @connection = ActiveRecord::Base.establish_connection("sdmstore_#{Rails.env}").connection
  end

  def change
    add_column :ref_high_level_statuses, :is_in_progress, :boolean, :default => true

    @connection = ActiveRecord::Base.establish_connection("#{Rails.env}").connection
  end
end

有必要重新设置连接以使其将迁移写入 schema_migrations 表,这样 rake 下次就不会尝试重新运行迁移。这假设您希望默认数据库配置中的 schema_migrations 表来跟踪签入相应项目版本控制的迁移。

我无法让向下迁移工作。

I got this to work with the following code.

class AddInProgressToRefHighLevelStatuses < ActiveRecord::Migration
  def connection
    @connection = ActiveRecord::Base.establish_connection("sdmstore_#{Rails.env}").connection
  end

  def change
    add_column :ref_high_level_statuses, :is_in_progress, :boolean, :default => true

    @connection = ActiveRecord::Base.establish_connection("#{Rails.env}").connection
  end
end

It was necessary to set the connection back to get it to write the migration to the schema_migrations table so rake would not try to re-run the migration the next time. This assumes that you want the schema_migrations table in the default database configuration to keep track of the migrations checked into version control for the corresponding project.

I was unable to get the down migration to work.

安静被遗忘 2024-08-11 19:34:12

您应该在 /config/environments 中定义其他数据库/环境。

之后,您可以使用以下命令来迁移该特定环境。

rake db:migrate RAILS_ENV=customenvironment

You should define the other databases/environments in /config/environments.

After that you can use the following command to migrate that specific environment.

rake db:migrate RAILS_ENV=customenvironment
剩一世无双 2024-08-11 19:34:12

我最近遇到了同样的问题。目标是将历史表拆分到不同的数据库,因为它已经很大并且仍在快速增长。

我开始尝试通过执行 ActiveRecord::Base.assessment_connection(:history_database) 来解决该问题,但在不关闭连接的情况下无法获得该方式的任何变体。最后我发现了下面的解决方案。

在进行此更改后的历史模型中:

class History < ActiveRecord::Base

  # Directs queries to a database specifically for History
  establish_connection :history_database

  ...
end

我能够在迁移中执行此操作并且效果完美:

class CreateHistoriesTableInHistoryDatabase < ActiveRecord::Migration
  def up
    History.connection.create_table :histories do |t|
      ...
    end
  end

  def down
    History.connection.drop_table :histories
  end
end

这将在不同的数据库中创建表,但会修改原始数据库中的 schema_migrations 表,以便迁移不会再次运行。

I recently struggled with the same problem. The goal was to split off a histories table to a different database since it was already so large and still growing very quickly.

I started trying to resolve it by doing ActiveRecord::Base.establish_connection(:history_database), but could not get any variations of that way to work without the connection being closed. Then finally I discovered the solution below.

In the History model after making this change:

class History < ActiveRecord::Base

  # Directs queries to a database specifically for History
  establish_connection :history_database

  ...
end

I was able to do this in the migration and it worked perfectly:

class CreateHistoriesTableInHistoryDatabase < ActiveRecord::Migration
  def up
    History.connection.create_table :histories do |t|
      ...
    end
  end

  def down
    History.connection.drop_table :histories
  end
end

This will create the table in a different database, yet modify the schema_migrations table in the original database so the migration does not run again.

女中豪杰 2024-08-11 19:34:12

有点晚了,但我今天正在处理这个问题,我想出了这个自定义的 rake 任务:

namespace :db do
  desc "Apply db tasks in custom databases, for example  rake db:alter[db:migrate,test-es] applies db:migrate on the database defined as test-es in databases.yml"
  task :alter, [:task,:database] => [:environment] do |t, args|
    require 'activerecord'
    puts "Applying #{args.task} on #{args.database}"
    ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[args.database])
    Rake::Task[args.task].invoke
  end
end

A bit late, but I was dealing with this problem today and I came up with this custom rake task:

namespace :db do
  desc "Apply db tasks in custom databases, for example  rake db:alter[db:migrate,test-es] applies db:migrate on the database defined as test-es in databases.yml"
  task :alter, [:task,:database] => [:environment] do |t, args|
    require 'activerecord'
    puts "Applying #{args.task} on #{args.database}"
    ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[args.database])
    Rake::Task[args.task].invoke
  end
end
沩ん囻菔务 2024-08-11 19:34:12

嘿,我已经研究了几天,最终得到了这个解决方案,只是想分享它,它可能会对某人有所帮助。

这是它的完整要点。 https://gist.github.com/rafaelchiti/5575309
它有详细信息和解释。但如果您需要的话,请在下面找到更多详细信息。

该方法基于向已知的 rake 任务 db:migrate、db:create、db:drop 添加命名空间,并使用不同的数据库执行这些任务。然后根据新的database.yml 文件的配置添加用于连接的基本活动记录(AR) 类。这样,您就不需要使用连接内容来解决迁移问题,并且可以获得干净的目录结构。

您的结构最终将像这样

config
  |- database.yml
  \- another_database.yml (using the same nomenclature of 'development', 'test', etc).

db
  |- migrate (default migrate directory)
  |- schema.rb
  |- seed.rb

another_db
  |- migrate (migrations for the second db)
  |- schema.rb (schema that will be auto generated for this db)
  |- seed.rb (seed file for the new db)

然后在代码中您可以创建一个基类并从这个新的database.yml 文件中读取配置,并仅在继承自该 AR 基类的模型上连接到它。 (要点中的示例)。

最好的!。

Hey I been digging into this for a few days and I ended up with this solution, just wanted to share it, it might help someone.

Here the complete gist for it. https://gist.github.com/rafaelchiti/5575309
It has details ans explanation. But find below more details if you need them.

The approach is based on adding a namespace to the already known rake tasks db:migrate, db:create, db:drop and perform those tasks with a different database. And then in adding a base active record (AR) class for connecting based on the configuration of the new database.yml file. This way you don't need to hack around the migrations with connection stuff and you get a clean directory structure.

Your structure will end up like this

config
  |- database.yml
  \- another_database.yml (using the same nomenclature of 'development', 'test', etc).

db
  |- migrate (default migrate directory)
  |- schema.rb
  |- seed.rb

another_db
  |- migrate (migrations for the second db)
  |- schema.rb (schema that will be auto generated for this db)
  |- seed.rb (seed file for the new db)

Then in your code you can create a base class and read the config from this new database.yml file and connect to it only on the models that inherit from that AR base class. (example in the gist).

Best!.

红颜悴 2024-08-11 19:34:12

继@Bryan Larsen之后,如果您使用抽象类将一系列模型附加到不同的数据库,并且想要在它们上迁移模式,那么您可以这样做:

class CreatePosts < ActiveRecord::Migration
    def connection
      Post.connection
    end
    def up
      ...
    end
end

使用如下设置的模型:

class Post < ReferenceData
end

class ReferenceData < ActiveRecord::Base
  self.abstract_class = true
  establish_connection "reference_data_#{Rails.env}"
end

Following on from @Bryan Larsen, if you're using an abstract Class to attach a series of models to a different database, and would like to migrate schemas on them, then you can do this:

class CreatePosts < ActiveRecord::Migration
    def connection
      Post.connection
    end
    def up
      ...
    end
end

with a model set up something like:

class Post < ReferenceData
end

and

class ReferenceData < ActiveRecord::Base
  self.abstract_class = true
  establish_connection "reference_data_#{Rails.env}"
end
顾忌 2024-08-11 19:34:12

对于 Rails 3.2,这就是我们所做的,用于上下迁移:

class CreateYourTable < ActiveRecord::Migration

  def connection
    @connection ||= ActiveRecord::Base.connection
  end

  def with_proper_connection
    @connection = YourTable.connection
    yield
    @connection = ActiveRecord::Base.connection
  end


  def up
    with_proper_connection do
      create_table :your_table do |t|
      end
    end
  end

  def down
    with_proper_connection do
      drop_table :your_table
    end
  end

end

For Rails 3.2, this is what we did, works with migrating up and down:

class CreateYourTable < ActiveRecord::Migration

  def connection
    @connection ||= ActiveRecord::Base.connection
  end

  def with_proper_connection
    @connection = YourTable.connection
    yield
    @connection = ActiveRecord::Base.connection
  end


  def up
    with_proper_connection do
      create_table :your_table do |t|
      end
    end
  end

  def down
    with_proper_connection do
      drop_table :your_table
    end
  end

end
夜司空 2024-08-11 19:34:12
module ActiveRecord::ConnectionSwitch
  def on_connection(options)
    raise ArgumentError, "Got nil object instead of db config options :(" if options.nil?
    ActiveRecord::Base.establish_connection(options)
    yield
  ensure
    ActiveRecord::Base.establish_connection ActiveRecord::Base.configurations[Rails.env]
  end
end

ActiveRecord.send :extend, ActiveRecord::ConnectionSwitch

如果你把它放在 config/initializers/ 中,你将能够执行如下操作:

ActiveRecord.on_connection ActiveRecord::Base.configurations['production'] do
  Widget.delete_all
end

这将删除生产数据库上的所有小部件,并确保与当前 Rails env 的数据库的连接重新建立之后成立。

如果您只想使其在迁移中可用,请扩展 ActiveRecord::Migration 类。

module ActiveRecord::ConnectionSwitch
  def on_connection(options)
    raise ArgumentError, "Got nil object instead of db config options :(" if options.nil?
    ActiveRecord::Base.establish_connection(options)
    yield
  ensure
    ActiveRecord::Base.establish_connection ActiveRecord::Base.configurations[Rails.env]
  end
end

ActiveRecord.send :extend, ActiveRecord::ConnectionSwitch

If you place this inside config/initializers/ you'll be able to do something like this:

ActiveRecord.on_connection ActiveRecord::Base.configurations['production'] do
  Widget.delete_all
end

This will delete all widgets on the production db and make sure the connection to the current Rails env's db is re-established after that.

If you just want to make it available in your migrations insead extend the ActiveRecord::Migration class.

ぃ弥猫深巷。 2024-08-11 19:34:12

在 Rails 3.2 中,向迁移添加连接方法不起作用。因此,所有的答案都

def connection
 @connection ||= ActiveRecord::Base.establish_connection
end

不起作用(无法down、不适用于change、连接丢失等)。原因是ActiveRecord::Migration 和 Migrator 类具有硬编码到 ActiveRecord::Base 全部 结束 地点

幸运的是这篇文章向我指出了这张票有一个很好的解决方案,即覆盖实际的 rake 任务

我最终使用了稍微不同的 rake 任务,以便我可以具体了解在不同数据库上运行的迁移(我们试图支持多个数据库版本):

这是我的 lib/task/database.rake

# Augment the main migration to migrate your engine, too.
task 'db:migrate', 'nine_four:db:migrate'

namespace :nine_four do
    namespace :db do
        desc 'Migrates the 9.4 database'
        task :migrate => :environment do
            with_engine_connection do
                ActiveRecord::Migrator.migrate("#{File.dirname(__FILE__)}/../../nine_four/migrate", ENV['VERSION'].try(:to_i))
            end
        end
    end
end

# Hack to temporarily connect AR::Base to your engine.
def with_engine_connection
    original = ActiveRecord::Base.remove_connection
    ActiveRecord::Base.establish_connection("#{ Rails.env }_nine_four")
    yield
ensure
    ActiveRecord::Base.establish_connection(original)
end

这允许我们放置迁移特定于其自己的子目录中的一个数据库(nine_four/migrations 而不是 db/migrations)。 它还为每个数据库提供了在架构和迁移版本方面的完全隔离。唯一的缺点是需要运行两个 rake 任务(db:migrate 和 nine_four:db:migrate)。

In rails 3.2, adding a connection method to your migration does NOT work. So all of the answers like

def connection
 @connection ||= ActiveRecord::Base.establish_connection
end

simply won't work (can't down, doesn't work with change, connection lost, etc.) The reason for this is that the ActiveRecord::Migration and Migrator class have connections hard-coded to ActiveRecord::Base all over the place.

Fortunately this post pointed me to this ticket which has a good solution, namely overriding the actual rake task.

I ended up using a slightly different rake task so that I could be specific about the migrations I run on the different database (we were trying to support multiple db versions):

Here's my lib/task/database.rake

# Augment the main migration to migrate your engine, too.
task 'db:migrate', 'nine_four:db:migrate'

namespace :nine_four do
    namespace :db do
        desc 'Migrates the 9.4 database'
        task :migrate => :environment do
            with_engine_connection do
                ActiveRecord::Migrator.migrate("#{File.dirname(__FILE__)}/../../nine_four/migrate", ENV['VERSION'].try(:to_i))
            end
        end
    end
end

# Hack to temporarily connect AR::Base to your engine.
def with_engine_connection
    original = ActiveRecord::Base.remove_connection
    ActiveRecord::Base.establish_connection("#{ Rails.env }_nine_four")
    yield
ensure
    ActiveRecord::Base.establish_connection(original)
end

This allows us to put migrations specific to one database in their own subdirectory (nine_four/migrations instead of db/migrations). It also gives each database total isolation in terms of their schema and migration versions. The only downside is having two rake tasks to run (db:migrate and nine_four:db:migrate).

黑寡妇 2024-08-11 19:34:12

除了在不同的环境中运行迁移之外,我还希望架构位于单独的文件中。您可以从命令行执行此操作:

RAILS_ENV=quiz_development SCHEMA=db/schema_quiz_development.rb rake db:migrate

但我喜欢自定义 rake 任务方法,因此我可以输入以下内容:

rake db:with[quiz_development, db:migrate]

这是 rake 任务:

namespace :db do
  desc "Run :task against :database"
  task :with, [:database,:task] => [:environment] do |t, args|
    puts "Applying #{args.task} to #{args.database}"
    ENV['SCHEMA'] ||= "#{Rails.root}/db/schema_#{args.database}.rb"
    begin
      oldRailsEnv = Rails.env
      Rails.env = args.database
      ActiveRecord::Base.establish_connection(args.database)
      Rake::Task[args.task].invoke
    ensure
      Rails.env = oldRailsEnv
    end
  end
end

In addition to running a migration in a different environment, I also want the schemas in separate files. You can do this from the command line:

RAILS_ENV=quiz_development SCHEMA=db/schema_quiz_development.rb rake db:migrate

But I like the custom rake task approach so I can type this instead:

rake db:with[quiz_development, db:migrate]

Here's the rake task:

namespace :db do
  desc "Run :task against :database"
  task :with, [:database,:task] => [:environment] do |t, args|
    puts "Applying #{args.task} to #{args.database}"
    ENV['SCHEMA'] ||= "#{Rails.root}/db/schema_#{args.database}.rb"
    begin
      oldRailsEnv = Rails.env
      Rails.env = args.database
      ActiveRecord::Base.establish_connection(args.database)
      Rake::Task[args.task].invoke
    ensure
      Rails.env = oldRailsEnv
    end
  end
end
对你的占有欲 2024-08-11 19:34:12

我找到了一个非常干净的方法来做到这一点:

class CreateScores < ActiveRecord::Migration

  class ScoresDB < ActiveRecord::Base
    establish_connection("scores_#{Rails.env}")
  end

  def connection
    ScoresDB.connection
  end

  def up
    create_table :scores do |t|
      t.text :account_id
      t.text :offer
    end
  end

  def down
    drop_table :scores
  end
end

I've found a great clean way to do this:

class CreateScores < ActiveRecord::Migration

  class ScoresDB < ActiveRecord::Base
    establish_connection("scores_#{Rails.env}")
  end

  def connection
    ScoresDB.connection
  end

  def up
    create_table :scores do |t|
      t.text :account_id
      t.text :offer
    end
  end

  def down
    drop_table :scores
  end
end
带刺的爱情 2024-08-11 19:34:12
class Article < ActiveRecord::Base

    ActiveRecord::Base.establish_connection(
      :adapter  => "mysql2",
      :host     => "localhost",
      :username => "root",
      :database => "test"
    )
end

并且:

class Artic < Aritcle
    self.table_name = 'test'

    def self.get_test_name()
        query = "select name from testing"
        tst = connection.select_all(query) #select_all is important!
        tst[0].fetch('name')
    end
end

您可以调用 Artic.get_test_name 来执行。

class Article < ActiveRecord::Base

    ActiveRecord::Base.establish_connection(
      :adapter  => "mysql2",
      :host     => "localhost",
      :username => "root",
      :database => "test"
    )
end

And:

class Artic < Aritcle
    self.table_name = 'test'

    def self.get_test_name()
        query = "select name from testing"
        tst = connection.select_all(query) #select_all is important!
        tst[0].fetch('name')
    end
end

You can call Artic.get_test_name in order to execute.

南冥有猫 2024-08-11 19:34:12

您可以使用此版本,它还支持 rake db:rollback :

class ChangeQuiz < ActiveRecord::Migration
  def connection
    ActiveRecord::Base.establish_connection("quiz_#{Rails.env}").connection
  end

  def reset_connection
    ActiveRecord::Base.establish_connection(Rails.env)
  end

  def up
    # make changes

    reset_connection
  end

  def self.down
    # reverse changes

    reset_connection
  end
end

You could use this version, which also supports rake db:rollback:

class ChangeQuiz < ActiveRecord::Migration
  def connection
    ActiveRecord::Base.establish_connection("quiz_#{Rails.env}").connection
  end

  def reset_connection
    ActiveRecord::Base.establish_connection(Rails.env)
  end

  def up
    # make changes

    reset_connection
  end

  def self.down
    # reverse changes

    reset_connection
  end
end
双手揣兜 2024-08-11 19:34:12

例如,我有一个study_history模型:

rails g model study_history lesson:references user:references history_type:references
  1. 在database.yml中定义mysql部分
player_records:
  adapter: mysql2
  encoding: utf8
  host: 1.2.3.4
  username: root
  password: 
  timeout: 5000
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 20 } %>
  database: player_records
  1. 修改StudyHistory模型,添加create_connect,它将连接上面的mysql数据库player_records(我首先在mysql服务器中添加了这个数据库):
class StudyHistory < ApplicationRecord
  establish_connection :player_records
  
  belongs_to :lesson
  belongs_to :user
  belongs_to :history_type
end
  1. 在迁移文件中使用connection来创建表:
class CreateStudyHistories < ActiveRecord::Migration[6.0]
  def change
    StudyHistory.connection.create_table :study_histories do |t|
      t.references :lesson, null: false
      t.references :user, null: false
      t.references :history_type, null: false

      t.timestamps
    end
  end
end

现在,你可以运行

rails db:migrate

就是这样,我在rails 6中进行了测试,它的工作方式就像一个魅力,你可以从不同的数据库组合(本地sqlite3和远程mysql)获取数据。

irb(main):029:0> StudyHistory.first.lesson
   (42.5ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_Z
ERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
  StudyHistory Load (30.0ms)  SELECT `study_histories`.* FROM `study_histories` ORDER BY `study_histories`.`id` ASC LIMIT 1
   (0.0ms)  
 SELECT sqlite_version(*)
  Lesson Load (0.1ms)  SELECT "lessons".* FROM "lessons" WHERE "lessons"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<Lesson id: 1, title: "people", cn: nil, description: nil, version: nil, course_id: 1, created_at: "2020-03-01 23:57
:02", updated_at: "2020-05-08 09:57:40", level: "aa", ready: false, pictureurl: "/pictures/kiss^boy and girl^boy^girl.jp
g">

For example, I have a study_history model:

rails g model study_history lesson:references user:references history_type:references
  1. Define mysql section in database.yml
player_records:
  adapter: mysql2
  encoding: utf8
  host: 1.2.3.4
  username: root
  password: 
  timeout: 5000
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 20 } %>
  database: player_records
  1. Modify the StudyHistory model, add establish_connect, it will connect your mysql database player_records above (I added this database in mysql server first):
class StudyHistory < ApplicationRecord
  establish_connection :player_records
  
  belongs_to :lesson
  belongs_to :user
  belongs_to :history_type
end
  1. Use connection in the migration file to create table:
class CreateStudyHistories < ActiveRecord::Migration[6.0]
  def change
    StudyHistory.connection.create_table :study_histories do |t|
      t.references :lesson, null: false
      t.references :user, null: false
      t.references :history_type, null: false

      t.timestamps
    end
  end
end

now, you can run

rails db:migrate

That's it, I tested in rails 6, it works like a charm, you can get your data from different databases combined( local sqlite3 and remote mysql).

irb(main):029:0> StudyHistory.first.lesson
   (42.5ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_Z
ERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
  StudyHistory Load (30.0ms)  SELECT `study_histories`.* FROM `study_histories` ORDER BY `study_histories`.`id` ASC LIMIT 1
   (0.0ms)  
 SELECT sqlite_version(*)
  Lesson Load (0.1ms)  SELECT "lessons".* FROM "lessons" WHERE "lessons"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<Lesson id: 1, title: "people", cn: nil, description: nil, version: nil, course_id: 1, created_at: "2020-03-01 23:57
:02", updated_at: "2020-05-08 09:57:40", level: "aa", ready: false, pictureurl: "/pictures/kiss^boy and girl^boy^girl.jp
g">
梨涡少年 2024-08-11 19:34:12

您是否尝试过使用 quiz_development 作为 RAILS_ENV(而不是尝试让它使用 "quiz_#{RAILS_ENV}")?

RAILS_ENV=quiz_development rake db:migrate

Have you tried using quiz_development as a RAILS_ENV (instead of trying to get it to use "quiz_#{RAILS_ENV}")?

RAILS_ENV=quiz_development rake db:migrate
笑看君怀她人 2024-08-11 19:34:12

您还可以将所有 quiz_ 相关的迁移移动到 db/ 目录中的单独子文件夹中,然后添加镜像常规迁移功能的 rake 任务,但会在该子目录中查找迁移。也许不是超级优雅,但它确实有效。您可以复制并粘贴 Rails 中已有的 rake 任务,然后对它们进行一些修改。

You can also move all your quiz_ related migrations into a separate subfolder in the db/ directory and then add rake tasks mirroring the regular migration functionality but that looks for the migrations in that subdirectory. Not super-elegant perhaps but it works. You can copy and paste the rake tasks already in rails and just modify them a bit.

潦草背影 2024-08-11 19:34:12

基于@TheDeadSerious 的回答:

module ActiveRecord::ConnectionSwitch  
  def on_connection(connection_spec_name)
    raise ArgumentError, "No connection specification name specified. It should be a valid spec from database.yml" unless connection_spec_name
    ActiveRecord::Base.establish_connection(connection_spec_name)
    yield
  ensure
    ActiveRecord::Base.establish_connection(Rails.env)
  end
end

ActiveRecord.send :extend, ActiveRecord::ConnectionSwitch

用法:

ActiveRecord.on_connection "sdmstore_#{Rails.env}" do
  Widget.delete_all
end

Based on @TheDeadSerious's answer:

module ActiveRecord::ConnectionSwitch  
  def on_connection(connection_spec_name)
    raise ArgumentError, "No connection specification name specified. It should be a valid spec from database.yml" unless connection_spec_name
    ActiveRecord::Base.establish_connection(connection_spec_name)
    yield
  ensure
    ActiveRecord::Base.establish_connection(Rails.env)
  end
end

ActiveRecord.send :extend, ActiveRecord::ConnectionSwitch

Usage:

ActiveRecord.on_connection "sdmstore_#{Rails.env}" do
  Widget.delete_all
end
晌融 2024-08-11 19:34:12

如果您想将 WordPress 帖子显示到您的 Rails 网站并且
你不想使用多魔法连接宝石。您可以使用以下代码从 WordPress 博客获取数据。

 class Article < ActiveRecord::Base

    ActiveRecord::Base.establish_connection(
     :adapter  => "mysql2",
     :host     => "localhost",
     :username => "root",
     :database => "blog"
    )

    self.table_name = 'wp_posts'

    def self.get_post_data()
        query = "select name from testing"
        tst = connection.select_all(query)
        tst[0].fetch('name')
    end
end

if you want to display the wordpress post to your rails website and
you don't want to use mult-magic connection gem. you can use the below code in order to get the data from wordpress blog.

 class Article < ActiveRecord::Base

    ActiveRecord::Base.establish_connection(
     :adapter  => "mysql2",
     :host     => "localhost",
     :username => "root",
     :database => "blog"
    )

    self.table_name = 'wp_posts'

    def self.get_post_data()
        query = "select name from testing"
        tst = connection.select_all(query)
        tst[0].fetch('name')
    end
end
半衬遮猫 2024-08-11 19:34:12

我通过为不同的数据库创建单独的连接器类并在迁移中使用它们来完成这项工作。

class AddExampleToTest < ActiveRecord::Migration
  def connection
    @connection = OtherDatabaseConnector.establish_connection("sdmstore_#{Rails.env}").connection
  end
  def up
    add_column :test, :example, :boolean, :default => true

    @connection = MainDatabaseConnector.establish_connection("#{Rails.env}").connection
  end
  def down
    remove_column :test, :example

    @connection = MainDatabaseConnector.establish_connection("#{Rails.env}").connection
  end
end

我们可以在初始化器中定义这些连接器类。

class MainDatabaseConnector < ActiveRecord::Base
end
class OtherDatabaseConnector < ActiveRecord::Base
end

ActiveRecord::Base 保留一个连接池,它是由类索引的哈希值。 在此处了解更多信息。因此,对单独的连接使用单独的类可以保护我们免受关闭连接错误的影响。

此外,使用 updown 而不是 change 允许我们毫无问题地回滚迁移。目前还没有弄清楚这其中的原因。

I got this working by creating separate connector classes for different databases and using them in the migrations.

class AddExampleToTest < ActiveRecord::Migration
  def connection
    @connection = OtherDatabaseConnector.establish_connection("sdmstore_#{Rails.env}").connection
  end
  def up
    add_column :test, :example, :boolean, :default => true

    @connection = MainDatabaseConnector.establish_connection("#{Rails.env}").connection
  end
  def down
    remove_column :test, :example

    @connection = MainDatabaseConnector.establish_connection("#{Rails.env}").connection
  end
end

We can define these connector classes in initializers.

class MainDatabaseConnector < ActiveRecord::Base
end
class OtherDatabaseConnector < ActiveRecord::Base
end

ActiveRecord::Base keeps a connection pool that is a hash indexed by the class. Read more here. So using separate classes for separate connections protects us from the closed connection error.

Also, using up and down instead of change allows us to rollback the migration without any issue. Still haven't figured out the reason for this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文