2011-01-15 2 views
28

Voglio creare schema.sql invece di schema.rb. Dopo aver cercato su google ho scoperto che si può fare impostando il formato dello schema sql in application.rb. Così mi sono messo seguendo application.rbschema.sql non creabile anche dopo aver impostato schema_format =: sql

config.active_record.schema_format = :sql 

Ma se ho impostato schema_format a: sql, schema.rb/schema.sql non si crea affatto. Se commento la riga sopra crea schema.rb ma ho bisogno di schema.sql. Io parto dal presupposto che avrà la struttura del database scaricati in esso e so che la struttura del database può essere scaricato utilizzando

rake db:structure:dump 

Ma voglio che sia fatto automaticamente quando il database viene migrato.

C'è qualcosa che mi manca o che si assume male?

risposta

33

Cinque mesi dopo la domanda originale il problema esiste ancora. La risposta è che hai fatto tutto correttamente, ma c'è un bug in Rails.

Anche in the guides sembra che tutto ciò che serve è quello di cambiare il formato da: ruby ​​a: sql, ma il compito migrazione è definito come questo (ActiveRecord/lib/active_record/railties/databases.rake linea 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 

Come si può vedere, non succede nulla a meno che lo schema_formato sia uguale: rubino. Il dumping automatico dello schema in formato SQL funzionava in Rails 1.x. Qualcosa è cambiato in Rails 2 e non è stato corretto.

Il problema è che anche se si riesce a creare lo schema in formato SQL, non è possibile caricarlo nel database e l'attività rake db:setup ignorerà la struttura del database.

Il bug è stato notato di recente: https://github.com/rails/rails/issues/715 (e issues/715), e c'è una patch al https://gist.github.com/971720

Si consiglia di attendere che il cerotto deve essere applicato Rails (la versione bordo ha ancora questo bug), oppure applicare la patch da soli (potrebbe essere necessario farlo manualmente, poiché i numeri di riga sono leggermente cambiati).


Soluzione:

Con bundler è relativamente difficile da rattoppare le librerie (gli aggiornamenti sono così facili, che sono fatte molto spesso ei percorsi sono inquinate con i numeri strani - almeno se si utilizzare bordo rotaie ;-), così, invece di patch direttamente il file, si consiglia di creare due file nella cartella 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 

e 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 

Avendo questi file, si hanno compiti monkeypatched rastrello, e ancora può facilmente aggiornare Rails. Naturalmente, è necessario monitorare le modifiche introdotte nel file activerecord/lib/active_record/railties/databases.rake e decidere se le modifiche sono ancora necessarie.

+1

Ti darei +10 se potessi, buona soluzione, risolto anche il mio caso. – KensoDev

+4

La buona notizia è che questo è stato affrontato. La cattiva notizia è che è nella versione 3.2.0 candidati senza alcun segno di essere riportato su 3.1.x. Chissà quando scenderà la 3.2.0 finale. Vedi commettere: https://github.com/rails/rails/commit/15fb4302b6ff16e641b6279a3530eb8ed97f2899 –

+0

Buone notizie ancora una volta, 3.2.0 è fuori! –

-3

È possibile che sia necessario eliminare schema.rb per la schema.sql da creare.

+1

non ho bisogno di. –

13

sto utilizzando guide 2.3.5, ma questo può applicarsi ai 3,0 così:

rake db: Struttura: discarica fa il trucco per me.

+0

Questo non funziona (almeno in Rails 3.2.7 che sto usando). Non riesce per me con un messaggio di ' 'schema_migrations' tabella non exist' che è vero perché sto cercando di scaricare lo schema di un database legacy che non ha questo Rails tabella specifica. – Andrew

+1

Correzione: Sembra che il file è stato creato structure.sql correttamente. Non sono sicuro del motivo per cui ho ricevuto questo errore. – Andrew