Подтвердить что ты не робот

Schema.sql не создается даже после установки schema_format =: sql

Я хочу создать schema.sql вместо schema.rb. После googling я обнаружил, что это можно сделать, установив формат схемы sql в application.rb. Поэтому я установил следующее в application.rb

config.active_record.schema_format = :sql

Но если я устанавливаю schema_format в: sql, schema.rb/schema.sql вообще не создается. Если я прокомментирую строку выше, она создаст schema.rb, но мне нужно schema.sql. Я предполагаю, что в нем будет сбрасываться структура базы данных Я знаю, что структуру базы данных можно сбросить с помощью

rake db:structure:dump 

Но я хочу, чтобы это было сделано автоматически, когда база данных была перенесена.

Есть ли что-то, чего я не вижу или ошибаюсь?

4b9b3361

Ответ 1

Через пять месяцев после первоначального вопроса проблема все еще существует. Ответ заключается в том, что вы все сделали правильно, но в Rails есть ошибка.

Даже в руководствах это похоже на то, что вам нужно изменить формат с: ruby ​​на: sql, но задача миграции определяется как это (activerecord/lib/active_record/railties/databases.rake line 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 будет игнорировать вашу структуру базы данных.

Недавно была замечена ошибка: https://github.com/rails/rails/issues/715вопросы /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 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 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 

Имея эти файлы, вы выполняете обезболивающие рейк-задачи, и вы все еще можете легко обновить Rails. Конечно, вы должны следить за изменениями, внесенными в файл activerecord/lib/active_record/railties/databases.rake, и решать, нужны ли изменения.

Ответ 2

Я использую rails 2.3.5, но это может относиться и к 3.0:

rake db: structure: dump делает трюк для меня.

Ответ 3

Возможно, вам нужно удалить schema.rb для создаваемого schema.sql.