2011-01-15 6 views
28

schema.rbの代わりにschema.sqlを作成したいとします。グーグルで検索したところ、application.rbにsqlスキーマ形式を設定することでこれを行うことができました。だから私はapplication.rbschema_format =:sqlを設定してもschema.sqlが作成されない

config.active_record.schema_format = :sql 

で次のように設定する。しかし、私はにschema_formatを設定している場合:SQL、schema.rb/schema.sqlは一切作成されません。上記の行にコメントすると、schema.rbが作成されますが、schema.sqlが必要です。私は、データベースの構造が

rake db:structure:dump 

を使用してダンプすることができます。しかし、私は、データベースを移行するとき、それは自動的に行われるようにしたいことを知っている、それはデータベース構造がそれにダンプしているだろうと仮定して ています。

私には間違っていると思われることはありますか?

答えて

33

元の質問の5か月後、問題は依然として存在します。その答えは、すべてを正しく行ったことですが、Railsにはバグがあります。 SQLが、移行タスクは(ActiveRecordの/ libに/ active_record/railties/databases.rakeライン155)このように定義されています:へのルビー:あなたが必要とするすべてのから形式を変更することがあるよう

でもthe guidesにそれが見えます

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が等しくない限り、何も起こりません:ルビーを。 Rails 1.xでは、スキーマをSQL形式で自動的にダンプしていました。 Rails 2で何かが変更され、修正されていません。

問題は、スキーマをSQL形式で作成しても、これをデータベースに読み込むタスクがなく、タスクrake db:setupがデータベース構造を無視するということです。 https://github.com/rails/rails/issues/715(およびissues/715)を、そしてあなたがパッチがレールに適用されるまで待機することがありhttps://gist.github.com/971720

のパッチは、(エッジバージョンはまだこのバグを持っている)があり、:

バグが最近注目されていますパッチを自分で適用してください(回線番号が少し変わったため手動で行う必要があるかもしれません)。


回避策:ライブラリを(アップグレードは、彼らは非常に頻繁に行われており、パスは奇妙な数字で汚染されていることを、とても簡単ですパッチを適用することが比較的難しいバンドラで

- 少なくとも場合代わりに、直接ファイルをパッチで、エッジレール;-)を使用するので、あなたはあなたのlib/tasksフォルダ内の2つのファイルを作成することもできます。

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 

は、これらのファイルを持って、あなたはすくいタスクをmonkeypatchedしている、とあなたはまだ簡単にRailsのをアップグレードすることができます。もちろん、ファイルactiverecord/lib/active_record/railties/databases.rakeに導入された変更を監視し、変更がまだ必要かどうかを判断する必要があります。

+1

もし私ができるならば、私はあなたに+10を与えるでしょう、良い解決策、私の場合も解決しました。 – KensoDev

+4

良いニュースは、これが対処されているということです。悪い知らせは、それが3.1.xに移植されたという兆候がない3.2.0リリースの候補にあるということです。 3.2.0の決勝がいつ中断するかは誰が知っていますか?コミットを参照してください:https://github.com/rails/rails/commit/15fb4302b6ff16e641b6279a3530eb8ed97f2899 –

+0

再び良いニュース、3.2.0が出ています! –

-3

それはあなたが作成するschema.sqlためschema.rbを削除する必要が可能です。

+1

私はそうする必要はありませんでした。 –

13

私はレール2.3.5を使用していますが、これは同様に3.0に適用される場合があります:

すくいデシベル:構造:ダンプは私のためのトリックを行います。

+0

これは動作しません(少なくとも私が使用しているRails 3.2.7では)。これは、私が 'table 'schema_migrations' does not exist'というメッセージを表示して失敗します。これは、このRails固有のテーブルを持たないレガシーデータベースのスキーマをダンプしようとしているためです。 – Andrew

+1

修正:structure.sqlファイルが正しく作成されたようです。なぜ私はこのエラーが発生していたかわからない。 – Andrew

関連する問題