导轨 5.1
我有一个使用 PostgreSQL 作为数据库的 RAILS 应用程序。我想从 RAILS 的角度导出/转储 RAILS 数据库数据。所以我独立于数据库。稍后我想使用这个导出/转储文件将数据加载/导入/播种回数据库。
我试过以下GEM:
seed_dump
它可以工作,但不能处理 HABTM 模型关系。
yaml_db, 它有效,但 yaml 格式不是 rails db:seed
这里有一个导出为JSON的实际例子。我使用 rake tasks 来做这种事情。在此示例中,我正在转储用户表。
namespace :dataexport do
desc 'export users who have logged in since 2017-06-30'
task :recent_users => :environment do
puts "Export users who have logged in since 2017-06-30"
# Get a file ready, the 'data' directory has already been added in Rails.root
filepath = File.join(Rails.root, 'data', 'recent_users.json')
puts "- exporting users into #{filepath}"
# The key here is to use 'as_json', otherwise you get an ActiveRecord_Relation object, which extends
# array, and works like in an array, but not for exporting
users = User.where('last_login > ?', '2017-06-30').as_json
# The pretty is nice so I can diff exports easily, if that's not important, JSON(users) will do
File.open(filepath, 'w') do |f|
f.write(JSON.pretty_generate(users))
end
puts "- dumped #{users.size} users"
end
end
然后导入
namespace :dataimport do
desc 'import users from recent users dump'
task :recent_users => :environment do
puts "Importing current users"
filepath = File.join(Rails.root, 'data', 'recent_users.json')
abort "Input file not found: #{filepath}" unless File.exist?(filepath)
current_users = JSON.parse(File.read(filepath))
current_users.each do |cu|
User.create(cu)
end
puts "- imported #{current_users.size} users"
end
end
有时作为导入过程的一部分,我想要一个干净的表来导入,在这种情况下,我会开始任务:
ActiveRecord::Base.connection.execute("TRUNCATE users")
这不是处理 Really Big 表的最佳方式,大于,哦,50,000 行,和/或有很多文本字段。在这种情况下,数据库本机转储/导入工具会更合适。
为了完整起见,这里有一个 HABTM 示例。仍然有一个链接表,但它没有模型,所以使用它做某事的唯一方法是原始 SQL。假设我们的用户有很多角色,反之亦然(用户 M:M 角色),例如:
class User < ApplicationRecord
has_and_belongs_to_many :roles
end
class Role < ApplicationRecord
has_and_belongs_to_many :users
end
必然会有一个名为
users_roles
的连接表,它有两列,user_id
和 role_id
。
查看 HABTM 上的 Rails 指南
要导出,我们必须直接执行SQL:
users_roles = ActiveRecord::Base.connection.execute("SELECT * from users_roles").as_json
# and write the file as before
并执行SQL导入
# read the file, same as before
user_roles.each do |ur|
ActiveRecord::Base.connection.execute("insert into users_roles (user_id, role_id) values ('#{ur[0]}', '#{ur[1]}')")
end
我同意人们所说的使用内置数据库工具来做到这一点。或者弄清楚是否有办法告诉数据库导出为 CSV,然后以这种方式导入。
但是,如果您真的想要一种与数据库无关的方式,还有另一种方式:使用您自己的 API。
我的意思是,在 2017 年,您的 Rails 应用程序真的不应该只输出 HTML,还应该输出 JSON。也许你将来想写一个 SPA 类型的应用程序,或者一个移动应用程序。确保除了 HTML 版本之外还有对象的 Javascript 表示是一个好主意。
所以,如果您的应用程序中有 /projects,请编写一个请求
/projects
作为 JSON 的脚本。将每个对象保存为自己的文件,然后在您的远程系统中将所有内容发回。
如果 JSON 表示中没有任何内容(即您没有列出项目中的所有用户),请确保也访问这些端点并将所有内容保存到单独的 JSON 文件中。
然后编写一个播放器脚本,将所有这些文件发布到您的目标服务。
这是一种方法。还有另一种方法是在 ActiveRecord 中完全用 Ruby 编写它——这可能作为某种用户数据导出功能很有用,所以这也可能是一种很棒的方法,但在我看来,“我们可以构建一个 Javascript 前端吗还是移动应用程序?”之前通常会被问到,“用户可以取出他们的数据吗”;)