我在Rails 3.0.7中存储过程和测试数据库存在问题。运行时
rake db:test:prepare
它从schema.rb迁移db表,而不是直接从迁移迁移。通过调用execute方法并传入CREATE FUNCTION foo() ... BEGIN ... END;
等SQL字符串,在迁移过程中创建过程。
经过研究,我发现你应该使用
config.active_record.schema_format =:sql
在application.rb
内。添加此行后,我执行了
rake db:structure:dump rake db:test:clone_structure
第一个应该将结构转储到development.sql
文件中,第二个应该从该文件创建测试数据库。但是我的存储过程和函数仍未出现在测试数据库中。如果有人知道这个问题。
将不胜感激。
我也尝试过运行rake db:test:再次准备,但仍然没有结果。
MySQL 5.5,Rails 3.0.7,Ruby 1.8.7。
提前致谢!
答案 0 :(得分:9)
没有其他rake任务,而structure_dump的定义如下:
# File activerecord/lib/active_record/connection_adapters/mysql_adapter.rb, line 354
def structure_dump #:nodoc:
if supports_views?
sql = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'"
else
sql = "SHOW TABLES"
end
select_all(sql).map do |table|
table.delete('Table_type')
select_one("SHOW CREATE TABLE #{quote_table_name(table.to_a.first.last)}")["Create Table"] + ";\n\n"
end.join("")
end
所以它显然只适用于表格,而不是程序,除非你将它单个化。
据我所知,唯一的解决方案是使用shell:
mysqldump -R -u <user> <development_database> | mysql -u <user> <test_database>
答案 1 :(得分:1)
免责声明:我不是Ruby-on-Rails程序员
严格地说,在MySQL方面,你基本上有两种方法来提取存储过程(SP)和存储函数(SF)。
请记住,mysql.proc和information_schema.routines为磁盘和内存中的SP提供了外壳。但是,有两个SQL语句可以检索它们:SHOW CREATE PROCEDURE和SHOW CREATE FUNCTION。
第一种方法是使用mysql.proc收集所有SP和SF,并将它们形成为暴露它们的SQL语句。
示例I我的测试数据库中有6个SP和2个SF。以下是为所有8个例程生成SQL的方法:
mysql> SELECT CONCAT('SHOW CREATE ',type,' `',db,'`.`',name,'`\\G') SQLStatements FROM mysql.proc;
+-----------------------------------------------------+
| SQLStatements |
+-----------------------------------------------------+
| SHOW CREATE PROCEDURE `test`.`CreateSampleTable`\G |
| SHOW CREATE PROCEDURE `test`.`CreateSampleTables`\G |
| SHOW CREATE PROCEDURE `test`.`GetMissingIntegers`\G |
| SHOW CREATE FUNCTION `test`.`GetTestTableCounts`\G |
| SHOW CREATE PROCEDURE `test`.`ImportWeeklyBatch`\G |
| SHOW CREATE FUNCTION `test`.`InsertName`\G |
| SHOW CREATE PROCEDURE `test`.`LoadSampleTables`\G |
| SHOW CREATE PROCEDURE `test`.`MigrateColumn`\G |
+-----------------------------------------------------+
8 rows in set (0.00 sec)
您可以循环访问并收集每个存储过程和函数所需的代码。
触发器必须单独收集。
在MySQL 5.x中,您可以使用此查询收集触发器:
mysql> SELECT CONCAT('SHOW CREATE TRIGGER `',trigger_schema,'`.`',trigger_name,'`\\G') SQLStatements FROM information_schema.triggers;
+--------------------------------------------------+
| SQLStatements |
+--------------------------------------------------+
| SHOW CREATE TRIGGER `test`.`AddPermTempKey`\G |
| SHOW CREATE TRIGGER `test`.`DeletePermTempKey`\G |
+--------------------------------------------------+
或节省时间UNION两个SQL语句
mysql> SELECT CONCAT('SHOW CREATE ',type,' `',db,'`.`',name,'`\\G') SQLStatements FROM mysql.proc UNION SELECT CONCAT('SHOW CREATE TRIGGER `',trigger_schema,'`.`',trigger_name,'`\\G') SQLStatements FROM information_schema.triggers;
+-----------------------------------------------------+
| SQLStatements |
+-----------------------------------------------------+
| SHOW CREATE PROCEDURE `test`.`CreateSampleTable`\G |
| SHOW CREATE PROCEDURE `test`.`CreateSampleTables`\G |
| SHOW CREATE PROCEDURE `test`.`GetMissingIntegers`\G |
| SHOW CREATE FUNCTION `test`.`GetTestTableCounts`\G |
| SHOW CREATE PROCEDURE `test`.`ImportWeeklyBatch`\G |
| SHOW CREATE FUNCTION `test`.`InsertName`\G |
| SHOW CREATE PROCEDURE `test`.`LoadSampleTables`\G |
| SHOW CREATE PROCEDURE `test`.`MigrateColumn`\G |
| SHOW CREATE TRIGGER `test`.`AddPermTempKey`\G |
| SHOW CREATE TRIGGER `test`.`DeletePermTempKey`\G |
+-----------------------------------------------------+
10 rows in set (0.07 sec)
第二种方式是DBA的首选方式,使用mysqldump。
这将在单个文件中收集所有表结构,SP,SF和触发器。
mysqldump -h... -u... -p... --no-data --routines --triggers --all-databases > MySQLSchema.sql
这样做会没有CREATE TABLE的东西:
mysqldump -h... -u... -p... --no-data --no-create-info --routines --triggers --all-databases > MySQLSchema.sql
试试这些!!!
答案 2 :(得分:1)
在Rails 5中添加了(我尚未测试过)rake db:structure:dump
对存储函数和过程的支持。请参阅this commit in the rails GitHub project。 --routines
的{{1}}标记描述为here。注意方法mysqldump
看起来与JanMinárik六年前回答时的情况截然不同。
答案 3 :(得分:0)
正在寻找如何做同样的事情然后看到了这个:http://guides.rubyonrails.org/migrations.html#types-of-schema-dumps
引用:
“db / schema.rb无法表达特定于数据库的项目,例如外键约束,触发器或存储过程。在迁移过程中,您可以执行自定义SQL语句,而模式转储器无法从数据库重新构建这些语句。如果您是使用这样的功能,你应该将架构格式设置为:sql。“
即:
config.active_record.schema_format =:sql
我自己还没有尝试过,所以我稍后会发布一个后续行动。
答案 4 :(得分:0)
我采用了Matthew Bass删除现有rake任务的方法,并使用带有RolandoMySQLDBA提供的选项的mysqldump重新定义了一个任务
http://matthewbass.com/2007/03/07/overriding-existing-rake-tasks/
Rake::TaskManager.class_eval do
def remove_task(task_name)
@tasks.delete(task_name.to_s)
end
end
def remove_task(task_name)
Rake.application.remove_task(task_name)
end
# Override existing test task to prevent integrations
# from being run unless specifically asked for
remove_task 'db:test:prepare'
namespace :db do
namespace :test do
desc "Create a db/schema.rb file"
task :prepare => :environment do
sh "mysqldump --routines --no-data -u root ni | mysql -u root ni_test"
end
end
end
答案 5 :(得分:0)
如果您想要Ruby转储(而不是SQL转储),您可以尝试使用此gem:
https://github.com/jovoto-team/trackless_triggers
它支持开箱即用的mysql转储触发器和函数,而不会引入新的rake任务。它基于tenderlove的trigger_happy插件。
答案 6 :(得分:0)
On Rails 4我把它作为db:test:load
rake任务的后加载钩子挂钩,如下所示:
require File.expand_path('../config/application', __FILE__)
Rails.application.load_tasks
namespace :db do
namespace :test do
task :post_load_hook do
re_create_sps
end
def re_create_sps
[20170905123456, 20170905123457].each do |version|
ActiveRecord::Migrator.run(
:down, ActiveRecord::Migrator.migrations_paths, version)
ActiveRecord::Migrator.run(
:up, ActiveRecord::Migrator.migrations_paths, version)
end
end
# stored procs must be restored each time.
end
end
Rake::Task['db:test:load'].enhance(['db:test:post_load_hook'])
这种方法会自动运行,因此您不必在每次测试运行时手动重新加载数据库,它只会影响db:test:load
任务,所以我认为它是相当孤立的。
恕我直言,在任务中有迁移ID有点难看,所以你可以选择将迁移代码提取到lib并从上面的迁移和Rake任务中调用它来清理它。