Rails 7中创建含dinner关联的Day模型时出现SQLite表不存在错误
Rails 7中创建含dinner的Day模型报错:SQLite3::SQLException: no such table: main.dinners
问题场景
我开发了一个简单的Rails 7周菜单应用,模型生成命令如下:
rails generate model WeeklyMenu monday:references tuesday:references wednesday:references thursday:references friday:references saturday:references sunday:references rails generate model Day lunch:references brunch:references dinner:references rails generate model Meal title:string description:text
模型代码:app/models/weekly_menu.rb
class WeeklyMenu < ApplicationRecord belongs_to :monday, class_name: 'Day' belongs_to :tuesday, class_name: 'Day' belongs_to :wednesday, class_name: 'Day' belongs_to :thursday, class_name: 'Day' belongs_to :friday, class_name: 'Day' belongs_to :saturday, class_name: 'Day' belongs_to :sunday, class_name: 'Day' end
app/models/day.rb
class Day < ApplicationRecord belongs_to :lunch, class_name: 'Meal' belongs_to :brunch, class_name: 'Meal' belongs_to :dinner, class_name: 'Meal' end
app/models/meal.rb
class Meal < ApplicationRecord end
创建数据时,仅含lunch或lunch+brunch的Day可正常创建,但含dinner的Day会报错:
v1 = Meal.create(title: 'Meal 1', description: 'Desc 1') v2 = Meal.create(title: 'Meal 2', description: 'Desc 2') v3 = Meal.create(title: 'Meal 3', description: 'Desc 3') day2 = Day.create(lunch: v1) # 正常 day3 = Day.create(lunch: v1, brunch: v2) # 正常 day1 = Day.create(lunch: v1, brunch: v2, dinner: v3) # 报错 day4 = Day.create(cena: v3, brunch: v2, lunch: v1) # 报错(注:此处cena为拼写错误,应为dinner)
报错信息:
Day Create (0.7ms) INSERT INTO "days" ("lunch_id", "brunch_id", "dinner_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["lunch_id", 6], ["brunch_id", 4], ["dinner_id", 5], ["created_at", "2023-07-03 02:21:40.793290"], ["updated_at", "2023-07-03 02:21:40.793290"]] TRANSACTION (0.1ms) rollback transaction /Users/dev/.rvm/gems/ruby-3.2.0/gems/sqlite3-1.6.3-arm64-darwin/lib/sqlite3/database.rb:152:in `initialize': SQLite3::SQLException: no such table: main.dinners (ActiveRecord::StatementInvalid)
问题根源
使用rails generate model Day lunch:references brunch:references dinner:references生成模型时,Rails默认会为每个references字段创建指向单数模型对应复数表的外键约束。比如dinner:references会默认生成指向dinners表的外键,但实际需求是关联Meal模型(对应meals表),数据库层面的外键约束与模型配置不匹配,导致插入数据时数据库找不到dinners表而报错。
解决步骤
1. 修正数据库外键约束
- 如果未运行迁移,直接修改
db/migrate/[timestamp]_create_days.rb文件:
class CreateDays < ActiveRecord::Migration[7.0] def change create_table :days do |t| # 指定外键指向meals表 t.references :lunch, null: false, foreign_key: { to_table: :meals } t.references :brunch, null: false, foreign_key: { to_table: :meals } t.references :dinner, null: false, foreign_key: { to_table: :meals } t.timestamps end end end
- 如果已运行迁移,生成新迁移修改外键:
rails generate migration FixDayForeignKeys
编辑新迁移文件db/migrate/[timestamp]_fix_day_foreign_keys.rb:
class FixDayForeignKeys < ActiveRecord::Migration[7.0] def change # 移除错误的外键约束 remove_foreign_key :days, :lunches remove_foreign_key :days, :brunches remove_foreign_key :days, :dinners # 添加正确的外键约束,指向meals表 add_foreign_key :days, :meals, column: :lunch_id add_foreign_key :days, :meals, column: :brunch_id add_foreign_key :days, :meals, column: :dinner_id end end
运行迁移:
rails db:migrate
2. 优化模型关联配置(可选但推荐)
明确指定外键让代码更清晰,避免歧义:
# app/models/day.rb class Day < ApplicationRecord belongs_to :lunch, class_name: 'Meal', foreign_key: 'lunch_id' belongs_to :brunch, class_name: 'Meal', foreign_key: 'brunch_id' belongs_to :dinner, class_name: 'Meal', foreign_key: 'dinner_id' end
3. 修正拼写错误
创建day4时的cena: v3需改为dinner: v3。
内容的提问来源于stack exchange,提问作者sara lance
相关产品推荐
相关产品推荐

