2011-01-15 26 views
28

Tôi muốn tạo schema.sql thay vì schema.rb. Sau khi googling xung quanh tôi thấy rằng nó có thể được thực hiện bằng cách thiết lập định dạng giản đồ sql trong application.rb. Vì vậy, tôi đặt sau trong application.rbschema.sql không tạo ngay cả sau khi thiết lập schema_format =: sql

config.active_record.schema_format = :sql 

Nhưng nếu tôi đặt schema_format thành: sql, schema.rb/schema.sql không được tạo ra chút nào. Nếu tôi nhận xét dòng trên nó tạo schema.rb nhưng tôi cần schema.sql. Tôi giả định rằng nó sẽ có cấu trúc cơ sở dữ liệu đổ vào nó và Tôi biết rằng cấu trúc cơ sở dữ liệu có thể được đổ bằng

rake db:structure:dump 

Nhưng tôi muốn nó được thực hiện tự động khi cơ sở dữ liệu được di chuyển.

Có điều gì tôi thiếu hoặc giả định sai không?

Trả lời

33

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 

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.

+1

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

+4

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 –

+0

Tin tốt nữa, 3.2.0 đã hết! –

-3

Có thể bạn cần xóa schema.rb để tạo schema.sql.

+1

Tôi không cần. –

13

Tôi đang sử dụng đường ray 2.3.5 nhưng điều này có thể áp dụng cho 3.0 cũng như:

rake db: cấu trúc: đổ hiện các trick cho tôi.

+0

Tính năng này không hoạt động (ít nhất là trong Rails 3.2.7 mà tôi đang sử dụng). Nó không thành công đối với tôi với một thông báo 'table' schema_migrations 'không tồn tại', điều này đúng bởi vì tôi đang cố gắng đổ lược đồ của một cơ sở dữ liệu kế thừa mà không có bảng cụ thể Rails này. – Andrew

+1

Hiệu chỉnh: Có vẻ như tệp struct.sql đã được tạo chính xác. Không chắc chắn lý do tại sao tôi đã nhận được lỗi này mặc dù. – Andrew

Các vấn đề liên quan