在与标准“生产”不同的数据库上使用 Rails Migration或“开发”
我有一个正在运行的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(20)
有一个更简单的答案。将其添加到您的迁移中:
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:
That's for Rails 3.1. For Rails 2.X or 3.0 it's a class function instead (eg
def self.connection
)我让它与以下代码一起使用。
有必要重新设置连接以使其将迁移写入 schema_migrations 表,这样 rake 下次就不会尝试重新运行迁移。这假设您希望默认数据库配置中的 schema_migrations 表来跟踪签入相应项目版本控制的迁移。
我无法让向下迁移工作。
I got this to work with the following code.
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.
您应该在 /config/environments 中定义其他数据库/环境。
之后,您可以使用以下命令来迁移该特定环境。
You should define the other databases/environments in /config/environments.
After that you can use the following command to migrate that specific environment.
我最近遇到了同样的问题。目标是将历史表拆分到不同的数据库,因为它已经很大并且仍在快速增长。
我开始尝试通过执行
ActiveRecord::Base.assessment_connection(:history_database)
来解决该问题,但在不关闭连接的情况下无法获得该方式的任何变体。最后我发现了下面的解决方案。在进行此更改后的历史模型中:
我能够在迁移中执行此操作并且效果完美:
这将在不同的数据库中创建表,但会修改原始数据库中的 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:
I was able to do this in the migration and it worked perfectly:
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.
有点晚了,但我今天正在处理这个问题,我想出了这个自定义的 rake 任务:
A bit late, but I was dealing with this problem today and I came up with this custom rake task:
嘿,我已经研究了几天,最终得到了这个解决方案,只是想分享它,它可能会对某人有所帮助。
这是它的完整要点。 https://gist.github.com/rafaelchiti/5575309
它有详细信息和解释。但如果您需要的话,请在下面找到更多详细信息。
该方法基于向已知的 rake 任务 db:migrate、db:create、db:drop 添加命名空间,并使用不同的数据库执行这些任务。然后根据新的database.yml 文件的配置添加用于连接的基本活动记录(AR) 类。这样,您就不需要使用连接内容来解决迁移问题,并且可以获得干净的目录结构。
您的结构最终将像这样
然后在代码中您可以创建一个基类并从这个新的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
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!.
继@Bryan Larsen之后,如果您使用抽象类将一系列模型附加到不同的数据库,并且想要在它们上迁移模式,那么您可以这样做:
使用如下设置的模型:
和
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:
with a model set up something like:
and
对于 Rails 3.2,这就是我们所做的,用于上下迁移:
For Rails 3.2, this is what we did, works with migrating up and down:
如果你把它放在
config/initializers/
中,你将能够执行如下操作:这将删除生产数据库上的所有小部件,并确保与当前 Rails env 的数据库的连接重新建立之后成立。
如果您只想使其在迁移中可用,请扩展
ActiveRecord::Migration
类。If you place this inside
config/initializers/
you'll be able to do something like this: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.在 Rails 3.2 中,向迁移添加连接方法不起作用。因此,所有的答案都
不起作用(无法
down
、不适用于change
、连接丢失等)。原因是ActiveRecord::Migration 和 Migrator 类具有硬编码到 ActiveRecord::Base 全部 结束 地点。幸运的是这篇文章向我指出了这张票有一个很好的解决方案,即覆盖实际的 rake 任务。
我最终使用了稍微不同的 rake 任务,以便我可以具体了解在不同数据库上运行的迁移(我们试图支持多个数据库版本):
这是我的 lib/task/database.rake
这允许我们放置迁移特定于其自己的子目录中的一个数据库(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
simply won't work (can't
down
, doesn't work withchange
, 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
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).
除了在不同的环境中运行迁移之外,我还希望架构位于单独的文件中。您可以从命令行执行此操作:
但我喜欢自定义 rake 任务方法,因此我可以输入以下内容:
这是 rake 任务:
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:
But I like the custom rake task approach so I can type this instead:
Here's the rake task:
我找到了一个非常干净的方法来做到这一点:
I've found a great clean way to do this:
并且:
您可以调用 Artic.get_test_name 来执行。
And:
You can call Artic.get_test_name in order to execute.
您可以使用此版本,它还支持 rake db:rollback :
You could use this version, which also supports
rake db:rollback
:例如,我有一个study_history模型:
现在,你可以运行
就是这样,我在rails 6中进行了测试,它的工作方式就像一个魅力,你可以从不同的数据库组合(本地sqlite3和远程mysql)获取数据。
For example, I have a study_history model:
now, you can run
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).
您是否尝试过使用 quiz_development 作为 RAILS_ENV(而不是尝试让它使用
"quiz_#{RAILS_ENV}"
)?Have you tried using quiz_development as a RAILS_ENV (instead of trying to get it to use
"quiz_#{RAILS_ENV}"
)?您还可以将所有 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.
基于@TheDeadSerious 的回答:
用法:
Based on @TheDeadSerious's answer:
Usage:
如果您想将 WordPress 帖子显示到您的 Rails 网站并且
你不想使用多魔法连接宝石。您可以使用以下代码从 WordPress 博客获取数据。
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.
我通过为不同的数据库创建单独的连接器类并在迁移中使用它们来完成这项工作。
我们可以在初始化器中定义这些连接器类。
ActiveRecord::Base 保留一个连接池,它是由类索引的哈希值。 在此处了解更多信息。因此,对单独的连接使用单独的类可以保护我们免受关闭连接错误的影响。
此外,使用
up
和down
而不是change
允许我们毫无问题地回滚迁移。目前还没有弄清楚这其中的原因。I got this working by creating separate connector classes for different databases and using them in the migrations.
We can define these connector classes in initializers.
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
anddown
instead ofchange
allows us to rollback the migration without any issue. Still haven't figured out the reason for this.