2008-09-23 173 views
2

我想确认以下分析是正确的:在Ruby on Rails中使用迁移

我正在RoR中构建Web应用程序。我为我的postgres数据库设计了一个数据结构(大约有70个表格;这个设计可能需要在开发过程中进行更改和添加,以反映Rails的处理方式。身份验证,我会擦洗他们,并替换任何RA要求。)。

我有一个shell脚本,它调用一系列.sql文件来填充表格和初始数据的空数据库(例如,Towns获得预填充的城镇)以及测试数据(例如,公司获得一些虚拟公司,所以我有数据可以玩)。

例如:

CREATE TABLE towns (
    id   integer PRIMARY KEY DEFAULT nextval ('towns_seq'), 
    county_id integer REFERENCES counties ON DELETE RESTRICT ON UPDATE CASCADE, 
    country_id integer REFERENCES countries ON DELETE RESTRICT ON UPDATE CASCADE NOT NULL, 
    name  text NOT NULL UNIQUE 
); 

命题0:数据持续时间超过应用程序长,所以我深信,我想在数据库级别上强制实施参照完整性,以及在我的回报率模型验证,尽管缺乏干燥等功效。

建议1:如果我用Migrations替换脚本和sql文件,目前不可能告诉我的Postgres数据库关于当前在迁移代码中的SQL DDL文件中设置的外键和其他约束。

命题2:迁移的优势在于对模式的更改与RoR模型代码一起版本化。但是,如果我将脚本和.sql文件保存在railsapp/db中,我可以轻松地对它们进行版本化。命题3:鉴于迁移缺乏我想要的功能,并提供我可以复制的好处,所以我没有理由考虑使用它们。所以我应该 - 在脚本/生成模型时间中进行跳转。

我的问题:如果命题0被接受,命题1,2,3是否为真,为什么?

谢谢!

+0

代码格式化:只需在每个代码行前使用4个空格。 StackOverflow会将其视为预格式化的块(包括缩进),并且大部分时间都会为其选择正确的语法突出显示。 – webmat 2008-09-23 12:46:40

+0

在那里,@webmat。 – 2008-10-08 13:17:26

+0

执行数据库设计时需要考虑的事项https://cbabhusal.wordpress.com/2015/08/16/ruby-on-rails-order-of-migration-generator-matters-in-initial-design/ – illusionist 2015-09-04 03:03:50

回答

10

在至少两种情况下,命题1是错误的 - 您可以使用像foreign_key_migrations这样的插件来执行以下:

def self.up 
    create_table :users do |t| 
    t.column :department_id, :integer, :references => :departments 
    end 
end 

它会在您的数据库相应的外键约束。

当然,您可能还想在DDL中执行其他操作,在这种情况下,第二种情况会变得更加引人注目:您不必在迁移中使用Ruby DSL。尝试execute方法,而不是:

def self.up 
    execute 'YOUR SQL HERE' 
end 

有了这一点,你可以保持您的迁移SQL脚本的内容,获得后者(最突出的是down方法的好处,你并没有解决您的原始问题)并保留你喜欢的较低级别的控件。

4

命题1错了:如果只使用迁移内部的直接SQL,那么您可以明确定义使用迁移的参照完整性,有关更多详细信息,请参阅this post

命题2:迁移的热门兴趣是能够逐步定义数据库模型,同时跟踪每次添加的更改并能够在以后轻松回滚任何此类更改。

您必须小心您创建/修改内容的顺序,但您可以这样做。

有一点要记住:rails更适合以应用为中心的设计。在Rails Way(tm)中,数据库只能通过应用程序活动记录层访问,并使用webservices将数据公开到外部。

+0

谢谢!我同意你关于Rails方式。但是我的应用程序早在FileMaker Pro中就已经开始了(你会相信吗)。它一次使用Tomcat,Velocity和Turbine进行网络化。毫无疑问,我希望在五年内使用ZiML在Holodeck上实现它。但数据仍然存在... – NickR 2008-09-23 12:14:44

1

1:您可能想尝试this plugin。尽管我没有尝试过,但它似乎能够通过迁移添加外键约束。

2:迁移的真正好处是能够在数据库的历史记录中来回移动。这对你的.sql文件来说并不容易。

3:看看上面提到的插件是否适合你,然后决定:)无论如何,如果你不使用它们,这不是一个大罪!

0

由于您使用的Postgres和可能不想安装插件foreign_key_migrations,这里是我做的,当我想用​​这两种迁移和外键约束。

我将一个SchemaStatements方法添加到ActiveRecord :: SchemaStatements,名为“add_fk_constraint”。 这可能会出现在一些集中式文件中,但在下面的示例迁移文件中,我只是将它放在了内联中。


module ActiveRecord 
    module ConnectionAdapters # :nodoc: 
    module SchemaStatements 
     # Example call: 
     # add_fk_constraint 'orders','advertiser_id','advertisers','id' 
     # "If you want add/alter a 'orders' record, then its 'advertiser_id' had 
     # better point to an existing 'advertisers' record with corresponsding 'id'" 
     def add_fk_constraint(table_name, referencing_col, referenced_table, referenced_col) 
     fk_name = "#{table_name}_#{referencing_col}" 
     sql = <<-ENDSQL 
      ALTER TABLE #{table_name} 
      ADD CONSTRAINT #{fk_name} 
      FOREIGN KEY (#{referencing_col}) REFERENCES #{referenced_table} (#{referenced_col}) 
      ON UPDATE NO ACTION ON DELETE CASCADE; 
      CREATE INDEX fki_#{fk_name} ON #{table_name}(#{referencing_col}); 
     ENDSQL 
     execute sql 
     end 
    end 
    end 
end 

class AdvertisersOrders < ActiveRecord::Migration 
    def self.up 
    create_table :advertisers do |t| 
     t.column :name,    :string, :null => false 
     t.column :net_id,    :integer, :null => false 
     t.column :source_service_id, :integer, :null => false, :default => 1 
     t.column :source_id,   :integer, :null => false 
    end 

    create_table :orders do |t| 
     t.column :name,    :string, :null => false 
     t.column :advertiser_id,  :integer, :null => false 
     t.column :source_id,   :integer, :null => false 
    end 
    add_fk_constraint 'orders','advertiser_id','advertisers','id' 
    end 

    def self.down 
    drop_table :orders 
    drop_table :advertisers 
    end 
end 

我希望这可以帮助别人。这对我来说非常有用,因为我需要使用SQL“COPY”调用加载大量外部提供的数据,但我发现迁移系统非常方便。