SQLite迁移从schema.rb文件中删除'add_index'和'add_foreign_key'

时间:2013-01-25 12:11:16

标签: mysql ruby-on-rails sqlite rails-migrations foreigner

我在同一个Rails项目中使用SQLite3和MySQL,但是在两台不同的计算机上。我注意到,当我运行所有迁移时生成的schema.rb对于两种环境看起来都不同。当我在SQLite3环境中运行迁移时,将从schema.rb文件中删除以下语句

add_index "places", ["user_id"], :name => "places_user_id_fk"
add_foreign_key "places", "users", :name => "places_user_id_fk"

请注意,我使用foreigner gem扩展了add_foreign_keyremove_foreign_key的迁移。

以下是与问题相关的迁移和模型:

# 20130123004056_create_places.rb
class CreatePlaces < ActiveRecord::Migration
  def change
    create_table :places do |t|
      t.string :name
      t.string :location
      t.integer :user_id
      t.timestamps
    end
  end
end

...

# 20130123234250_add_foreign_key.rb
class AddForeignKey < ActiveRecord::Migration
  def change
    add_foreign_key(:places, :users)
  end
end

...

# user.rb
class User < ActiveRecord::Base
  has_many :places
end

...

# place.rb
class Place < ActiveRecord::Base
  belongs_to :user    
end

问题:如何以SQLite3和MySQL可以处理的方式定义usersplaces之间的关系?

1 个答案:

答案 0 :(得分:0)

foreigner README明确说明

  

支持以下适配器:

     
      
  • sqlite (外键方法是无操作)
  •   

因此,您的SQLite数据库没有设置的外键约束,因为foreigner不支持它们。从SQLite数据库生成db/schema.rb时,这就是没有指定外键的原因。

Rails Guide on Migrations提到外键很多

  

如果需要执行特定于数据库的任务(例如创建外键约束),则execute方法允许您执行任意SQL

甚至有how to add/remove a foreign key的例子。

在第一次使用Rails时使用foreigner,我建议您从Gemfile中删除

  1. 根本不要使用外键;只需在ActiveRecord关联中指定级联
  2. 使用上面链接示例中描述的execute迁移方法(并确保所有不同的RDBMS'支持您放入execute方法中的任何内容) < / LI>
  3. 如果您坚持使用外键,请停止在开发中使用SQLite。你不会在生产中使用SQLite,并且已经在其他机器上使用更好的RDMS(MySQL,“更好”,因为它有正在寻找的外键支持)。
  4. 作为评论中的pointed out,SQLite在创建表后缺乏对添加外键的支持;它们无法通过Rails中的未来迁移添加。 我个人建议您使用选项1或3 ,因为在满足SQLite限制但同时具有相同最终结果的迁移中通过execute命令创建解决方案会更加困难在其他RDMS上。