即使在设置schema_format =:sql之后,schema.sql也无法创建

我想创建schema.sql而不是schema.rb。 谷歌搜索后我发现可以通过在application.rb设置sql架构格式来完成。 所以我在application.rb中设置了以下内容

 config.active_record.schema_format = :sql 

但是如果我将schema_format设置为:sql,则根本不会创建schema.rb / schema.sql。 如果我在上面注释它创建schema.rb,但我需要schema.sql。 我假设它将在其中转储数据库结构,我知道可以使用转储数据库结构

 rake db:structure:dump 

但是我希望在迁移数据库时自动完成它。

我有什么遗漏或假设错了吗?

原问题提出五个月后问题仍然存在。 答案是你做的一切都正确,但Rails中有一个错误。

即使在指南中 ,您看起来所需要的只是将格式从:ruby更改为:sql,但是迁移任务是这样定义的(activerecord / lib / active_record / railties / databases.rake第155行):

 task :migrate => [:environment, :load_config] do ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, ENV["VERSION"] ? ENV["VERSION"].to_i : nil) db_namespace["schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end 

如您所见,除非schema_format等于:ruby,否则不会发生任何事情。 在Rails 1.x中,以SQL格式自动转储模式。 Rails 2中的某些内容已经发生了变化,并且尚未修复。

问题是,即使您设法以SQL格式创建模式,也没有任务将其加载到数据库中,任务rake db:setup将忽略您的数据库结构。

最近已经注意到这个bug: https : //github.com/rails/rails/issues/715 (和issues / 715 ),并在https://gist.github.com/971720上有一个补丁

您可能希望等到修补程序应用于Rails(边缘版本仍然存在此错误),或者自己应用修补程序(您可能需要手动执行此操作,因为行号已稍微更改)。


解决方法:

使用bundler来修补库是相对困难的(升级是如此简单,以至于它们经常被完成并且路径被奇怪的数字污染 – 至少如果你使用边缘轨道;-) ,所以,而不是直接修补文件,您可能想在lib/tasks文件夹中创建两个文件:

lib/tasks/schema_format.rake

 import File.expand_path(File.dirname(__FILE__)+"/schema_format.rb") # Loads the *_structure.sql file into current environment's database. # This is a slightly modified copy of the 'test:clone_structure' task. def db_load_structure(filename) abcs = ActiveRecord::Base.configurations case abcs[Rails.env]['adapter'] when /mysql/ ActiveRecord::Base.establish_connection(Rails.env) ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0') IO.readlines(filename).join.split("\n\n").each do |table| ActiveRecord::Base.connection.execute(table) end when /postgresql/ ENV['PGHOST'] = abcs[Rails.env]['host'] if abcs[Rails.env]['host'] ENV['PGPORT'] = abcs[Rails.env]['port'].to_s if abcs[Rails.env]['port'] ENV['PGPASSWORD'] = abcs[Rails.env]['password'].to_s if abcs[Rails.env]['password'] `psql -U "#{abcs[Rails.env]['username']}" -f #{filename} #{abcs[Rails.env]['database']} #{abcs[Rails.env]['template']}` when /sqlite/ dbfile = abcs[Rails.env]['database'] || abcs[Rails.env]['dbfile'] `sqlite3 #{dbfile} < #{filename}` when 'sqlserver' `osql -E -S #{abcs[Rails.env]['host']} -d #{abcs[Rails.env]['database']} -i #{filename}` # There was a relative path. Is that important? : db\\#{Rails.env}_structure.sql` when 'oci', 'oracle' ActiveRecord::Base.establish_connection(Rails.env) IO.readlines(filename).join.split(";\n\n").each do |ddl| ActiveRecord::Base.connection.execute(ddl) end when 'firebird' set_firebird_env(abcs[Rails.env]) db_string = firebird_db_string(abcs[Rails.env]) sh "isql -i #{filename} #{db_string}" else raise "Task not supported by '#{abcs[Rails.env]['adapter']}'" end end namespace :db do namespace :structure do desc "Load development_structure.sql file into the current environment's database" task :load => :environment do file_env = 'development' # From which environment you want the structure? # You may use a parameter or define different tasks. db_load_structure "#{Rails.root}/db/#{file_env}_structure.sql" end end end 

lib/tasks/schema_format.rb

 def dump_structure_if_sql Rake::Task['db:structure:dump'].invoke if ActiveRecord::Base.schema_format == :sql end Rake::Task['db:migrate' ].enhance do dump_structure_if_sql end Rake::Task['db:migrate:up' ].enhance do dump_structure_if_sql end Rake::Task['db:migrate:down'].enhance do dump_structure_if_sql end Rake::Task['db:rollback' ].enhance do dump_structure_if_sql end Rake::Task['db:forward' ].enhance do dump_structure_if_sql end Rake::Task['db:structure:dump'].enhance do # If not reenabled, then in db:migrate:redo task the dump would be called only once, # and would contain only the state after the down-migration. Rake::Task['db:structure:dump'].reenable end # The 'db:setup' task needs to be rewritten. Rake::Task['db:setup'].clear.enhance(['environment']) do # see the .clear method invoked? Rake::Task['db:create'].invoke Rake::Task['db:schema:load'].invoke if ActiveRecord::Base.schema_format == :ruby Rake::Task['db:structure:load'].invoke if ActiveRecord::Base.schema_format == :sql Rake::Task['db:seed'].invoke end 

拥有这些文件,你有monkeypatched rake任务,你仍然可以轻松升级Rails。 当然,您应该监视文件activerecord/lib/active_record/railties/databases.rake引入的更改,并确定是否仍需要进行修改。

我正在使用rails 2.3.5,但这也适用于3.0:

rake db:structure:dump对我有用。

您可能需要删除schema.rb以创建schema.sql