Ruby on Rails:如何创建以字符串作为主键的数据库表的引用

问题描述 投票:0回答:1

我对ROR并不陌生,现在正在做一个与书籍有关的课程项目。我有一个以字符串'isbn'作为其主键的“书”表,现在尝试用外键“ isbn”的书表添加另一个“注释”来引用“书”表。所以我的“ models / comment.rb”看起来像这样:

class Comment < ApplicationRecord
  belongs_to :book, references: :isbn, type: :string
end 

并且“ models / book.rb”是:

class Book < ApplicationRecord
  has_many :comments, dependent: :destroy
end

我的“书”表如下所示:SQLite view for books table我希望数据库迁移后生成的“ comments”表将包含列“ isbn”(字符串),但实际上生成的“ comments”表包含“ book_id”(整数)。enter image description here如何生成外键以引用“书”表中的字符串主键“ isbn”?

ruby-on-rails
1个回答
3
投票

首先将外键列设置为正确的类型,然后将外键约束设置为指向右列:

class CreateComments < ActiveRecord::Migration[6.0]
  def change
    create_table :comments do |t|
      t.string :title
      t.string :note
      t.references :book, type: :string, column_name: :isbn
      t.timestamps
    end
  end
end

我希望生成的“评论”表将包含一个数据库迁移后的列“ isbn”(字符串),但实际上是“注释”生成的表包含“ book_id”(整数)。

实际上,迁移比您想象的要简单很多。它只是创建SQL语句的DSL。它实际上并没有以任何方式知道另一个表,因此它无法知道books.isbn是一个字符串列。它仅使用add_reference的默认类型为:integer。 Rails是由惯例驱动的,而不是人工智能。

如果要调用该列之类的其他内容,例如book_isbn,则必须分两步进行:

class CreateComments < ActiveRecord::Migration[6.0]
  def change
    create_table :comments do |t|
      t.string :title
      t.string :note
      t.string :book_isbn
      t.timestamps
    end
    add_foreign_key :comments, :books, 
       column: "book_isbn", primary_key: "isbn"
  end
end

然后设置书籍模型以使用您的非传统主键:

class Book < ApplicationRecord
  self.primary_key = :isbn
  has_many :comments, 
    foreign_key: :book_isbn # default is book_id
end

在注释方面,您需要配置belongs_to关联,以便它指向books.isbn而不是books.id

class Comment < ApplicationRecord
  belongs_to :book, primary_key: :isbn
end

[references不是belongs_to的有效选项。

ArgumentError (Unknown key: :references. Valid keys are: :class_name, :anonymous_class, :foreign_key, :validate, :autosave, :foreign_type, :dependent, :primary_key, :inverse_of, :required, :polymorphic, :touch, :counter_cache, :optional, :default)
© www.soinside.com 2019 - 2024. All rights reserved.