【问题标题】:Rails 5.2 migrations conundrum, create primary key and foreign keysRails 5.2 迁移难题,创建主键和外键
【发布时间】:2018-07-25 02:58:32
【问题描述】:

我无法弄清楚我的迁移出了什么问题,但它们不起作用,试图从类别中的主键中添加产品的外键 20180724203015_create_categories.rb

class CreateCategories < ActiveRecord::Migration[5.2]
   def change
    create_table :categories, id: false do |t|
      t.string :name
      t.text :description
      t.integer :category_id, primary_key: true, auto_increment: true
      t.timestamps
    end
  end
end

20180724203105_create_products.rb

 class CreateProducts < ActiveRecord::Migration[5.2]
  def change
    create_table :products do |t|

      t.string :name
      t.references :category_id, foreign_key: true, index: true

      t.timestamps
    end
  end
end

然而这总是以错误结束,不能添加外键约束

【问题讨论】:

  • 多说“行不通”。
  • 我正在尝试将产品添加到站点内的类别中,但是数据库中没有存储任何内容,因为它给出了一条错误消息,说明类别必须存在,我认为是因为产品表中的 :category_id 仍然为空,我希望它使用关联的 category_id 填充,我从中创建产品...
  • 其实我只需要主键 :category_id 在分类上,外键 :category_id 在产品上,这样我就可以关联表格了。
  • 你为什么使用category_id作为categories的主键而不是传统的id
  • 我不确定如何将表从 :id 到 :id 关联到每个表,rails 是否创建 category_id?换句话说,我如何将表从 :id 到 :id 从类别关联到产品?

标签: mysql ruby-on-rails ruby devise


【解决方案1】:

Ruby on Rails 采用约定优于配置的原则。这意味着如果您遵循 Rails 约定,事情会容易得多,并且几乎不需要任何配置。

在您的迁移中,您决定与 Rails 约定之一作斗争:数据库的主键存储在 id 列中。当你决定不遵循这个约定时,你不能再简单地使用 references 方法而不告诉 Rails 你是如何设置数据库的。

我的建议是:除非你有非常非常好的理由,否则不要反对 Rails 约定。它不仅会使这项任务(数据库迁移)变得更加复杂,而且还会增加其他需要更多配置(例如 ActiveRecord 模型)的风险,或者当您将 Rails 更新到较新版本时,可能会出现问题。 /p>

也就是说:更改您的迁移以使用 Rails 约定:

# 20180724203015_create_categories.rb
class CreateCategories < ActiveRecord::Migration[5.2]
   def change
    create_table :categories do |t| # <- create an `id` column per default
      t.string :name
      t.text :description

      t.timestamps
    end
  end
end

# 20180724203105_create_products.rb
class CreateProducts < ActiveRecord::Migration[5.2]
  def change
    create_table :products do |t|
      t.references :category, foreign_key: true # <- just name the relation

      t.string :name

      t.timestamps
    end
  end
end

【讨论】:

    【解决方案2】:

    对此的答案是删除 t.integer :category_id,并依赖 rails 的 :id 列用于每个表,可以使用 @category 或 @product 进行引用,如 cmets 中所述 - @category = Cateogory.find(params[:id]) 或 Category.find(params[:category_id]) 因为我相信这就是它在路线中的引用方式。谢谢。

    【讨论】:

      猜你喜欢
      • 2011-03-19
      • 1970-01-01
      • 2016-06-06
      • 1970-01-01
      • 2016-11-20
      • 1970-01-01
      • 2021-10-16
      • 2014-03-11
      • 1970-01-01
      相关资源
      最近更新 更多