Ruby на Rails: как создать ссылку на таблицу БД со строкой в ​​качестве первичного ключа - PullRequest
0 голосов
/ 07 апреля 2020

Я новичок в ROR, и сейчас делаю учебный проект, связанный с книгами. У меня есть таблица «book» со строкой «isbn» в качестве первичного ключа, и теперь я пытаюсь добавить еще один «комментарий» со ссылкой на таблицу book с внешним ключом «isbn» для ссылки на таблицу «book». Итак, мой "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

Моя таблица "books" выглядит следующим образом: SQLite view for books table Я ожидал бы, что сгенерированная таблица «comments» будет содержать столбец «isbn» (строка) после переноса базы данных, но на самом деле сгенерированная таблица «comments» содержала вместо этого «book_id» (целое число) , enter image description here Как мне сгенерировать внешний ключ для ссылки на первичный ключ строки "isbn" в таблице "book"?

1 Ответ

3 голосов
/ 07 апреля 2020

Начните с установки правильного типа столбца внешнего ключа и установите ограничение внешнего ключа, указывающее на правый столбец:

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» (строка) после переноса базы данных, но на самом деле сгенерированная таблица «comments» содержала вместо него «book_id» (целое число).

Миграции на самом деле намного проще и тупее, чем вы думаете. Это просто DSL, который создает SQL операторов. На самом деле он никак не знает о другой таблице, поэтому он не может знать, что 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

Затем настройте модель books для использования вашего нетрадиционного первичного ключа:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...