0

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

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

请注意,我使用了通过和扩展迁移的外国人 gemadd_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 都可以处理的users关系places

4

1 回答 1

0

自述foreigner 文件明确指出

支持以下适配器:

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

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

Rails Guide on Migrations多次提到外键

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

甚至还有一个如何添加/删除外键的示例。

foreigner刚开始使用 Rails 时使用过,我建议你将它从你的Gemfile或者

  1. 根本不要使用外键;只需在 ActiveRecord 关联中指定您的级联
  2. 使用execute上面链接示例中描述的迁移方法(并确保所有不同的 RDBMS 支持您在execute方法中输入的任何内容)
  3. 如果您坚持使用外键,请停止在开发中使用 SQLite。无论如何,您不会在生产中使用 SQLite,并且已经在其他机器上使用更好的 RDMS(MySQL,“更好”,因为它具有正在寻找的外键支持)。

正如您在评论中指出的那样,SQLite 缺乏在创建表后添加外键的支持;它们不能通过 Rails 中的未来迁移添加。我个人建议您使用选项 1 或 3execute ,因为通过迁移中的命令创建满足 SQLite 限制同时在其他 RDMS 上具有相同最终结果的解决方案将更加困难。

于 2013-01-25T15:15:40.853 回答