2011-01-15 13 views
28

Ich möchte schema.sql anstelle von schema.rb erstellen. Nach dem googlen fand ich, dass es getan werden kann, indem man das sql Schemaformat in application.rb einstellt. So folgt Ich habe in application.rbschema.sql nicht selbst nach dem Festlegen von schema_format = erstellen: sql

config.active_record.schema_format = :sql 

Aber wenn ich gesetzt schema_format zu: sql, schema.rb/schema.sql ist gar nicht erstellt. Wenn ich die obige Zeile kommentiere, erstellt sie schema.rb, aber ich brauche schema.sql. Ich gehe davon aus, dass es Datenbankstruktur in sich geworfen hat und Ich weiß, dass die Datenbankstruktur abgeladen werden kann

rake db:structure:dump 

verwenden, aber ich mag es automatisch zu tun, wenn Datenbank migriert wird.

Gibt es etwas, was ich vermisse oder falsch vermute?

Antwort

33

Fünf Monate nach der ursprünglichen Frage existiert das Problem noch. Die Antwort ist, dass Sie alles richtig gemacht haben, aber es gibt einen Fehler in Rails.

Auch in the guides sieht es aus wie alles, was Sie brauchen, um das Format zu ändern, stammt von: Ruby: SQL, aber die Migrate Aufgabe wird wie folgt definiert (Active/lib/active_record/railties/databases.rake Linie 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 

Wie Sie sehen können, passiert nichts, außer das Schema_format ist gleich: ruby. Automatisches Dumping des Schemas im SQL-Format funktionierte in Rails 1.x. In Rails 2 hat sich etwas geändert und wurde nicht repariert.

Das Problem ist, dass, selbst wenn Sie das Schema im SQL-Format erstellen, gibt es keine Aufgabe, diese in die Datenbank zu laden, und die Aufgabe rake db:setup ignoriert Ihre Datenbankstruktur.

Der Fehler wurde vor kurzem bemerkt: https://github.com/rails/rails/issues/715 (und issues/715) und es einen Patch

bei https://gist.github.com/971720

ist Möglicherweise möchten Sie warten, bis der Patch auf Rails angelegt wird (die Kante Version hat noch diesen Fehler), oder wenden Sie den Patch selbst an (Sie müssen dies möglicherweise manuell tun, da sich die Zeilennummern ein wenig geändert haben).


Umgehung:

Mit bundler es relativ schwierig ist, die Bibliotheken patchen (Upgrades sind so einfach, dass sie sehr oft getan werden und die Wege sind mit seltsamen Zahlen verunreinigt - zumindest wenn man verwendet Kantenschienen ;-), so, anstatt die Datei direkt von Patchen, sollten Sie zwei Dateien in Ihrem lib/tasks Ordner erstellen:

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 

und 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 

diese Dateien zu haben, haben Sie Rake Aufgaben monkeypatched, und Sie können immer noch leicht aktualisieren Rails. Natürlich sollten Sie die Änderungen in der Datei activerecord/lib/active_record/railties/databases.rake überwachen und entscheiden, ob die Änderungen noch notwendig sind.

+1

Ich würde Ihnen +10 geben, wenn ich könnte, gute Lösung, löste auch meinen Fall. – KensoDev

+4

Die gute Nachricht ist, dass dies angesprochen wurde. Die schlechte Nachricht ist, dass es in den Release-Kandidaten der Version 3.2.0 enthalten ist, ohne dass es signiert ist, dass es zurück auf Version 3.1.x portiert wurde. Wer weiß, wann 3.2.0 endgültig fallen wird. Siehe commit: https://github.com/rails/rails/commit/15fb4302b6ff16e641b6279a3530eb8ed97f2899 –

+0

Gute Nachrichten wieder, 3.2.0 ist out! –

-3

Es ist möglich, dass Sie die schema.rb für die zu erstellende schema.sql löschen müssen.

+1

Ich musste nicht. –

13

Ich bin mit Schienen 2.3.5 aber dies bis 3,0 gelten als gut:

rake db: Struktur: dump funktioniert der Trick für mich.

+0

Dies funktioniert nicht (zumindest in Rails 3.2.7, die ich verwende). Es scheitert für mich mit einer Nachricht von 'Tabelle 'schema_migrations' existiert nicht ', was wahr ist, weil ich versuche, das Schema einer Legacy-Datenbank zu erstellen, die diese Rails-spezifische Tabelle nicht hat. – Andrew

+1

Korrektur: Es sieht so aus, als ob die Datei structure.sql korrekt erstellt wurde. Nicht sicher, warum ich diesen Fehler bekommen habe. – Andrew

Verwandte Themen