【问题标题】:schema.sql not creating even after setting schema_format = :sql即使在设置 schema_format = :sql 后,schema.sql 也没有创​​建
【发布时间】:2011-06-09 13:36:30
【问题描述】:

我想创建 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 

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

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

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 schema


    【解决方案1】:

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

    即使在the guides 中,您似乎只需将格式从 :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,否则不会发生任何事情。 以 SQL 格式自动转储模式在 Rails 1.x 中工作。 Rails 2 发生了一些变化,但尚未修复。

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

    最近发现了这个bug:https://github.com/rails/rails/issues/715(和issues/715),在https://gist.github.com/971720有一个补丁

    你可能想等到补丁应用到 Rails (边缘版本仍然有这个 bug),或者自己应用补丁(你可能需要手动做,因为行号已经改变了一点)。


    解决方法:

    使用 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 
    

    有了这些文件,你就有了猴子补丁的 rake 任务,你仍然可以轻松地升级 Rails。当然,您应该监视文件activerecord/lib/active_record/railties/databases.rake 中引入的更改,并决定是否仍然需要修改。

    【讨论】:

    • 如果可以的话,我会给你+10,很好的解决方案,也解决了我的问题。
    • 好消息是这个问题已经得到解决。坏消息是它在 3.2.0 候选版本中,没有迹象表明它被移植到 3.1.x。谁知道3.2.0 final什么时候会掉。见提交:github.com/rails/rails/commit/…
    • 又是好消息,3.2.0 出来了!
    • 坏消息来了,在 Rails 3.2.3 中,“rake db:setup”被破坏了 schema_format :sql (github.com/rails/rails/pull/2948#issuecomment-5832017)
    • 您好,我通过仅覆盖两个 db:schema:{load,dump} 任务对它进行了一些修改,并且还添加了一些转储和加载数据的实用程序任务。你可以在这里找到来源:gist.github.com/4548844 :-)
    【解决方案2】:

    我使用的是 rails 2.3.5,但这也可能适用于 3.0:

    rake db:structure:dump 对我有用。

    【讨论】:

    • 这不起作用(至少在我使用的 Rails 3.2.7 中)。它对我来说失败并显示table 'schema_migrations' doesn't exist 的消息,这是真的,因为我正在尝试转储没有此 Rails 特定表的旧数据库的架构。
    • 更正:似乎结构.sql 文件已正确创建。不知道为什么我会收到这个错误。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-02
      • 2019-04-16
      • 2021-08-17
      • 1970-01-01
      • 1970-01-01
      • 2013-05-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多