在 Rails 的 Ruby 中的现有列上创建外键
Creating a foreign key on an exisiting column in Ruby on Rails
我正在尝试在 Rails 上的 Ruby 中创建两个 table,它们都将通过播种 CSV 文件来填充。这两个文件都已经包含一个 ID 列 fsa_id
,我想将其用作 table 的 primary/foreign 键。
到目前为止,我有以下 table 个迁移:
姓名:
class CreateNames < ActiveRecord::Migration[6.0]
def change
create_table :names do |t|
t.integer :fsa_id
t.string :name
t.timestamps
end
end
end
地点:
class CreateLocations < ActiveRecord::Migration[6.0]
def change
create_table :locations do |t|
t.integer :fsa_id
t.string :adress
t.string :postcode
t.integer :lattitude
t.integer :longitude
t.string :local_authority
t.timestamps
end
end
end
我想要做的是使 fsa_id
成为名称 table 的主键和位置 table.
的外键
据我所知,我可以通过将以下内容添加到位置迁移文件来做到这一点:
class CreateLocations < ActiveRecord::Migration[6.0]
def change
create_table :locations do |t|
t.integer :fsa_id
t.string :adress
t.string :postcode
t.integer :lattitude
t.integer :longitude
t.string :local_authority
t.timestamps
end
# Adds a foreign key constraint to the fsa_id column
# Links to the names table which uses the same named column.
add_foreign_key :locations,
:names,
column: :fsa_id,
primary_key: :fsa_id
end
end
但是,当我添加它并尝试 运行 rails db:migrate
时,我收到以下错误:
== 20201116221428 CreateLocations: migrating ==================================
-- create_table(:locations)
-> 0.0017s
-- add_foreign_key(:locations, :names, {:column=>:fsa_id, :primary_key=>:fsa_id})
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:
SQLite3::SQLException: foreign key mismatch - "locations" referencing "names"
/home/jonathon/Projects/waad/jpd_individual_2020/db/migrate/20201116221428_create_locations.rb:15:in `change'
/home/jonathon/Projects/waad/jpd_individual_2020/bin/rails:9:in `<top (required)>'
/home/jonathon/Projects/waad/jpd_individual_2020/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
Caused by:
ActiveRecord::StatementInvalid: SQLite3::SQLException: foreign key mismatch - "locations" referencing "names"
/home/jonathon/Projects/waad/jpd_individual_2020/db/migrate/20201116221428_create_locations.rb:15:in `change'
/home/jonathon/Projects/waad/jpd_individual_2020/bin/rails:9:in `<top (required)>'
/home/jonathon/Projects/waad/jpd_individual_2020/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
Caused by:
SQLite3::SQLException: foreign key mismatch - "locations" referencing "names"
/home/jonathon/Projects/waad/jpd_individual_2020/db/migrate/20201116221428_create_locations.rb:15:in `change'
/home/jonathon/Projects/waad/jpd_individual_2020/bin/rails:9:in `<top (required)>'
/home/jonathon/Projects/waad/jpd_individual_2020/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
我试过环顾四周,但大多数答案似乎假设要么使用 table 的 id
,要么 table 会自行增长。
作为数据库种子的 CSV 文件的完整参考布局如下:
names.csv:
locations.csv:
如果有人能帮助解决这个问题,我将不胜感激。
编辑:
我在生产中使用 Postgress:
我的Gemfile如下:
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby '2.6.5'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.3', '>= 6.0.3.4'
# Use sqlite3 as the database for Active Record
gem 'sqlite3', '~> 1.4', '>= 1.4.2', group: :production
# Use Puma as the app server
gem 'puma', '~> 4.1'
# Use SCSS for stylesheets
gem 'sass-rails', '>= 6'
# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
gem 'webpacker', '~> 4.0'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.7'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use Active Model has_secure_password
# gem 'bcrypt', '~> 3.1.7'
gem 'chartkick'
# Use Active Storage variant
# gem 'image_processing', '~> 1.2'
# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.4.2', require: false
group :production do
gem 'pg'
end
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end
group :development do
# Access an interactive console on exception pages or by calling 'console' anywhere in the code.
gem 'web-console', '>= 3.3.0'
gem 'listen', '~> 3.2'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
end
group :test do
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '>= 2.15'
gem 'selenium-webdriver'
# Easy installation and use of web drivers to run system tests with browsers
gem 'webdrivers'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
在 CreateNames
迁移中,您可以使用 primary_key: :fsa_id
选项。
class CreateNames < ActiveRecord::Migration[6.0]
def change
create_table :names, primary_key: :fsa_id do |t|
t.string :name
t.timestamps
end
end
end
CreateLocations
迁移与您发布的一样。
您还需要在以下模型中设置关联:
class Name < ApplicationRecord
has_one :location, primary_key: :fsa_id
end
class Location < ApplicationRecord
belongs_to :name, foreign_key: :fsa_id, primary_key: :fsa_id
end
如果您想修改现有的外键或向其添加外键 table,您应该创建一个新的迁移以避免在生产中破坏代码。
我正在尝试在 Rails 上的 Ruby 中创建两个 table,它们都将通过播种 CSV 文件来填充。这两个文件都已经包含一个 ID 列 fsa_id
,我想将其用作 table 的 primary/foreign 键。
到目前为止,我有以下 table 个迁移:
姓名:
class CreateNames < ActiveRecord::Migration[6.0]
def change
create_table :names do |t|
t.integer :fsa_id
t.string :name
t.timestamps
end
end
end
地点:
class CreateLocations < ActiveRecord::Migration[6.0]
def change
create_table :locations do |t|
t.integer :fsa_id
t.string :adress
t.string :postcode
t.integer :lattitude
t.integer :longitude
t.string :local_authority
t.timestamps
end
end
end
我想要做的是使 fsa_id
成为名称 table 的主键和位置 table.
据我所知,我可以通过将以下内容添加到位置迁移文件来做到这一点:
class CreateLocations < ActiveRecord::Migration[6.0]
def change
create_table :locations do |t|
t.integer :fsa_id
t.string :adress
t.string :postcode
t.integer :lattitude
t.integer :longitude
t.string :local_authority
t.timestamps
end
# Adds a foreign key constraint to the fsa_id column
# Links to the names table which uses the same named column.
add_foreign_key :locations,
:names,
column: :fsa_id,
primary_key: :fsa_id
end
end
但是,当我添加它并尝试 运行 rails db:migrate
时,我收到以下错误:
== 20201116221428 CreateLocations: migrating ==================================
-- create_table(:locations)
-> 0.0017s
-- add_foreign_key(:locations, :names, {:column=>:fsa_id, :primary_key=>:fsa_id})
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:
SQLite3::SQLException: foreign key mismatch - "locations" referencing "names"
/home/jonathon/Projects/waad/jpd_individual_2020/db/migrate/20201116221428_create_locations.rb:15:in `change'
/home/jonathon/Projects/waad/jpd_individual_2020/bin/rails:9:in `<top (required)>'
/home/jonathon/Projects/waad/jpd_individual_2020/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
Caused by:
ActiveRecord::StatementInvalid: SQLite3::SQLException: foreign key mismatch - "locations" referencing "names"
/home/jonathon/Projects/waad/jpd_individual_2020/db/migrate/20201116221428_create_locations.rb:15:in `change'
/home/jonathon/Projects/waad/jpd_individual_2020/bin/rails:9:in `<top (required)>'
/home/jonathon/Projects/waad/jpd_individual_2020/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
Caused by:
SQLite3::SQLException: foreign key mismatch - "locations" referencing "names"
/home/jonathon/Projects/waad/jpd_individual_2020/db/migrate/20201116221428_create_locations.rb:15:in `change'
/home/jonathon/Projects/waad/jpd_individual_2020/bin/rails:9:in `<top (required)>'
/home/jonathon/Projects/waad/jpd_individual_2020/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
我试过环顾四周,但大多数答案似乎假设要么使用 table 的 id
,要么 table 会自行增长。
作为数据库种子的 CSV 文件的完整参考布局如下:
names.csv:
locations.csv:
如果有人能帮助解决这个问题,我将不胜感激。
编辑:
我在生产中使用 Postgress:
我的Gemfile如下:
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby '2.6.5'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.3', '>= 6.0.3.4'
# Use sqlite3 as the database for Active Record
gem 'sqlite3', '~> 1.4', '>= 1.4.2', group: :production
# Use Puma as the app server
gem 'puma', '~> 4.1'
# Use SCSS for stylesheets
gem 'sass-rails', '>= 6'
# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
gem 'webpacker', '~> 4.0'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.7'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use Active Model has_secure_password
# gem 'bcrypt', '~> 3.1.7'
gem 'chartkick'
# Use Active Storage variant
# gem 'image_processing', '~> 1.2'
# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.4.2', require: false
group :production do
gem 'pg'
end
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end
group :development do
# Access an interactive console on exception pages or by calling 'console' anywhere in the code.
gem 'web-console', '>= 3.3.0'
gem 'listen', '~> 3.2'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
end
group :test do
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '>= 2.15'
gem 'selenium-webdriver'
# Easy installation and use of web drivers to run system tests with browsers
gem 'webdrivers'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
在 CreateNames
迁移中,您可以使用 primary_key: :fsa_id
选项。
class CreateNames < ActiveRecord::Migration[6.0]
def change
create_table :names, primary_key: :fsa_id do |t|
t.string :name
t.timestamps
end
end
end
CreateLocations
迁移与您发布的一样。
您还需要在以下模型中设置关联:
class Name < ApplicationRecord
has_one :location, primary_key: :fsa_id
end
class Location < ApplicationRecord
belongs_to :name, foreign_key: :fsa_id, primary_key: :fsa_id
end
如果您想修改现有的外键或向其添加外键 table,您应该创建一个新的迁移以避免在生产中破坏代码。