2011-01-15 13 views
28

Chcę utworzyć schema.sql zamiast schema.rb. Po przejściu go dookoła znalazłem, że można to zrobić, ustawiając format schematu sql w application.rb. Tak ustawić następujące w environment.rbSchema.sql nie tworzy nawet po ustawieniu schema_format =: sql

config.active_record.schema_format = :sql 

Ale jeśli ustawić schema_format do: SQL, schema.rb/schema.sql nie powstaje w ogóle. Jeśli komentarz do powyższej linii tworzy schema.rb, ale potrzebuję schema.sql. Jestem zakładając, że będzie miał strukturę bazy danych rzucił w niego i wiem, że struktura bazy danych może być sprzedawany po cenach dumpingowych z użyciem

rake db:structure:dump 

Ale chcę to być zrobione automatycznie, gdy baza danych jest migracja.

Czy jest coś, czego mi brakuje lub zakładam, że jest nie tak?

Odpowiedz

33

Pięć miesięcy po pierwotnym pytaniu problem nadal istnieje. Odpowiedź brzmi, że zrobiłeś wszystko poprawnie, ale w Railsach jest błąd.

Nawet w the guides wygląda na to wszystko, co potrzebne jest, aby zmienić format z Ruby do: SQL, ale zadanie Migrate jest zdefiniowany następująco (activerecord/lib/active_record/railties/databases.rake linia 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 

Jak widać, nic się nie dzieje, chyba że schemat ma format: ruby. Automatyczne odrzucanie schematu w formacie SQL działało w Railsach 1.x. Coś się zmieniło w Rails 2 i nie zostało naprawione.

Problem polega na tym, że nawet jeśli uda się utworzyć schemat w formacie SQL, nie ma zadania, aby załadować je do bazy danych, a zadanie rake db:setup zignoruje strukturę bazy danych.

Błąd został zauważony niedawno: https://github.com/rails/rails/issues/715 (i issues/715), a tam jest łata na https://gist.github.com/971720

Możesz poczekać, aż łata jest nakładana na Rails (wersja krawędź nadal ma ten błąd) lub zastosuj łatkę samodzielnie (może być konieczne ręczne wykonanie, ponieważ numery linii zmieniły się nieznacznie).


Obejście:

Z Bundler jest stosunkowo trudno załatać bibliotek (aktualizacje są tak łatwe, że są one wykonywane bardzo często i ścieżki są zanieczyszczone dziwnych numerów - przynajmniej jeśli używać krawędź szyny ;-), więc zamiast łatania plik bezpośrednio, może chcesz utworzyć dwa pliki w folderze 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 

i 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 

Mając te pliki, trzeba monkeypatched zadania Rake, a nadal można łatwo uaktualnić szynach. Oczywiście powinieneś monitorować zmiany wprowadzone w pliku activerecord/lib/active_record/railties/databases.rake i zdecydować, czy modyfikacje są nadal konieczne.

+1

Dałbym ci +10, gdybym mógł, dobre rozwiązanie, również rozwiązał moją sprawę. – KensoDev

+4

Dobrą wiadomością jest to, że zostało to rozwiązane. Złą wiadomością jest to, że znajduje się on w wersjach 3.2.0, bez żadnych oznak przywracania ich do wersji 3.1.x. Kto wie, kiedy skończy się wersja 3.2.0. Zobacz commit: https://github.com/rails/rails/commit/15fb4302b6ff16e641b6279a3530eb8ed97f2899 –

+0

Dobra wiadomość ponownie, 3.2.0 jest już dostępny! –

-3

Możliwe, że należy usunąć schema.rb, aby można było utworzyć .

+1

Nie potrzebowałem. –

13

Używam szyn 2.3.5, ale może to mieć zastosowanie do 3,0, a także:

rake db: strukturę: zrzucić załatwia sprawę dla mnie.

+0

To nie działa (przynajmniej w Railsach 3.2.7, których używam). To nie działa dla mnie z komunikatem 'table 'schema_migrations" nie istnieje ", co jest prawdą, ponieważ próbuję zrzucić schemat starej bazy danych, która nie ma tej konkretnej tabeli Rails. – Andrew

+1

Korekta: Wygląda na to, że plik structure.sql został poprawnie utworzony. Nie wiem, dlaczego otrzymałem ten błąd. – Andrew