Năm tháng sau câu hỏi ban đầu, sự cố vẫn tồn tại. Câu trả lời là bạn đã làm mọi thứ một cách chính xác, nhưng có một lỗi trong Rails.
Ngay cả trong the guides nó trông giống như tất cả các bạn cần là thay đổi định dạng từ: ruby để: sql, nhưng nhiệm vụ di cư được định nghĩa như thế này (activerecord/lib/active_record/railties/databases.rake dòng 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
Như bạn có thể thấy, không có gì xảy ra trừ khi schema_format bằng: ruby. Tự động bán phá giá lược đồ ở định dạng SQL đang hoạt động trong Rails 1.x. Một cái gì đó đã thay đổi trong Rails 2, và đã không được cố định.
Vấn đề là ngay cả khi bạn quản lý để tạo giản đồ trong định dạng SQL, không có nhiệm vụ để tải này vào cơ sở dữ liệu, và nhiệm vụ rake db:setup
sẽ bỏ qua cấu trúc cơ sở dữ liệu của bạn.
Các lỗi đã được nhận thấy thời gian gần đây: https://github.com/rails/rails/issues/715 (và issues/715), và có một miếng vá ở https://gist.github.com/971720
Bạn có thể muốn đợi cho đến khi bản vá được áp dụng cho Rails (phiên bản cạnh vẫn có lỗi này), hoặc áp dụng bản vá cho chính mình (bạn có thể cần phải làm điều đó theo cách thủ công, vì số dòng đã thay đổi một chút).
Cách giải quyết:
Với bundler nó tương đối khó để vá các thư viện (nâng cấp rất dễ dàng, rằng họ đang thực hiện rất thường xuyên và những con đường đang bị ô nhiễm với những con số kỳ lạ - ít nhất là nếu bạn sử dụng cạnh đường ray ;-), vì vậy, thay vì vá các tập tin trực tiếp, bạn có thể muốn tạo ra hai tập tin trong thư mục lib/tasks
của bạn:
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
và 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
Có những tập tin này, bạn đã monkeypatched nhiệm vụ cào, và bạn vẫn có thể dễ dàng nâng cấp Rails. Tất nhiên, bạn nên theo dõi các thay đổi được giới thiệu trong tập tin activerecord/lib/active_record/railties/databases.rake
và quyết định xem các sửa đổi vẫn còn cần thiết.
Tôi sẽ cung cấp cho bạn 10 nếu tôi có thể, giải pháp tốt, giải quyết trường hợp của tôi là tốt. – KensoDev
Tin tốt là điều này đã được giải quyết. Tin xấu là nó nằm trong các ứng cử viên phát hành 3.2.0 mà không có dấu hiệu của nó được chuyển về 3.1.x. Ai biết được khi nào thì trận chung kết 3.2.0 sẽ giảm. Xem cam kết: https://github.com/rails/rails/commit/15fb4302b6ff16e641b6279a3530eb8ed97f2899 –
Tin tốt nữa, 3.2.0 đã hết! –