rails db:使用ActiveRecord :: RecordInvalid导致种子错误:验证失败:类别必须存在

时间:2017-11-30 12:42:44

标签: mysql ruby-on-rails ruby activerecord ruby-on-rails-5

好的,所以我发誓这个种子文件以前正在工作,但是现在每当我尝试运行rails db:seed命令时我都会收到错误:

rails aborted!
ActiveRecord::RecordInvalid: Validation failed: Category must exist
/home/krefey/dev/sonar/db/seeds.rb:12:in `<top (required)>'
/home/krefey/dev/sonar/bin/rails:9:in `require'
/home/krefey/dev/sonar/bin/rails:9:in `<top (required)>'
/home/krefey/dev/sonar/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
Tasks: TOP => db:seed

我使用的是最新的rails版本,我的数据库是MySQL

我的种子文件是:

Category.create!(name: 'Miniatures')
Category.create!(name: 'Cardgames')
Category.create!(name: 'Boardgames')
Category.create!(name: 'RPG')
Game.create!(name: 'Warhammer 40,000', category_id: Category.find_by(name:'Miniatures'))
Game.create!(name: 'Age of Sigmar', category_id: Category.find_by(name: 'Miniatures'))
Game.create!(name: 'Necromunda', category_id: Category.find_by(name: 'Miniatures'))
Game.create!(name: 'Warmachine', category_id: Category.find_by(name: 'Miniatures'))
Game.create!(name: 'Hordes', category_id: Category.find_by(name: 'Miniatures'))
Game.create!(name: 'Infinity', category_id: Category.find_by(name: 'Miniatures'))
Game.create!(name: 'Munchkin', category_id: Category.find_by(name: 'Cardgames'))
Game.create!(name: 'Cardgamess Against Humanity', category_id: Category.find_by(name: 'Cardgames'))
Game.create!(name: 'Choking Hazard', category_id: Category.find_by(name: 'Cardgames'))
Game.create!(name: 'Poker', category_id: Category.find_by(name: 'Cardgames'))
Game.create!(name: 'Bridge', category_id: Category.find_by(name: 'Cardgames'))
Game.create!(name: 'Risk', category_id: Category.find_by(name: 'Boardgames'))
Game.create!(name: 'Twighlight Imperium', category_id: Category.find_by(name: 'Boardgames'))
Game.create!(name: 'Shadespire', category_id: Category.find_by(name: 'Boardgames'))
Game.create!(name: 'Settlers of Catan', category_id: Category.find_by(name: 'Boardgames'))
Game.create!(name: 'Carcasonne', category_id: Category.find_by(name: 'Boardgames'))
Game.create!(name: 'Dungeons & Dragons', category_id: Category.find_by(name: 'RPG'))
Game.create!(name: 'Pathfinder', category_id: Category.find_by(name: 'RPG'))
Game.create!(name: '7th Sea', category_id: Category.find_by(name: 'RPG'))
Game.create!(name: 'Legend of the 5 Rings', category_id: Category.find_by(name: 'RPG'))
Game.create!(name: 'GURPS', category: Category.find_by(name: 'RPG'))

类别模型:

class Category < ApplicationRecord
  has_many :games
  validates :name, inclusion: { in: %w(Miniatures RPG Cardgames Boardgames),
    message: "%{value} is not a valid game type"}, presence: true
end

游戏模型:

class Game < ApplicationRecord
  belongs_to :category

  def self.search(search)
    where("content LIKE ?", "%#{search}%")
  end
end

模式

ActiveRecord::Schema.define(version: 20171130120931) do

  create_table "categories", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "games", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.string "name"
    t.bigint "category_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["category_id"], name: "index_games_on_category_id"
  end

  add_foreign_key "games", "categories"
end

该错误似乎在抱怨Category.find_by部分。但我不明白为什么。类别模型存在于模式中。我可以成功删除表,创建表并运行迁移,但是当我尝试运行db:seed命令时它会失败(或者它到达db:reset命令的db:seed部分)。

如果我添加

optional: true

游戏模型的代码,然后种子工作,但category_id字段没有填充并显示为nil。那么,我哪里错了?为什么我似乎不能在游戏桌中填充category_id的外键列?

3 个答案:

答案 0 :(得分:0)

我认为这样的重构将解决你的堆栈跟踪并使你的种子更具可读性:

?lapply

答案 1 :(得分:0)

我认为你不能将模型对象分配给ID。两种正确的可能性可能是:

Game.create!(name: 'Warhammer 40,000', category: Category.find_by(name:'Miniatures'))
# or also possible, but ugly:
Game.create!(name: 'Warhammer 40,000', category_id: Category.find_by(name:'Miniatures').id)

如AntonTkachov所述,您应该重构代码,以摆脱所有find_by次调用。

答案 2 :(得分:0)

您可以按照Association proxies in Active Record 所述使用创建,如下所示:

# db/seeds.rb

miniatures = Category.create(name: 'Miniatures')
miniatures.games.create([
  { name: 'Warharmmer 40,000' },
  { name: 'Age of Sigmar' },
  { name: 'Necromunda' }
])

card = Category.create(name: 'Cardgames')
card.games.create([
  { name: 'Muchkin' },
  { name: 'Cardgames Against Humanity' },
  { name: 'Chocking Hazard' }
])

我怀疑你的种子文件以前工作的原因是因为你没有使用Rails 5,这使得belongs_to关联默认需要。有关详细信息,请参阅Abhishek Jain的帖子。