You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails种子文件编写遇语法错误与NotNullViolation错误求助

修复Rails Kudo种子文件的问题

我正在编写生成随机Kudo的Rails种子文件,Kudo包含Title、Content(用Faker生成,这部分没问题),还有giver_id和receiver_id外键,希望在不同用户间随机生成Kudo,但尝试多种写法都出错了:

第一种写法及错误

employees = Employee.create!([{email: Faker::Internet.email(domain: 'gmail.com'), password: 'password'},{email: Faker::Internet.email(domain: 'gmail.com'), password: 'password'},...])

kudos = Kudo.create!(Title: Faker::Adjective.positive, Content: Faker::Company.bs, Kudo.new(giver:Employee.create()), Kudo.new(receiver:Employee.create()))

报错信息:

SyntaxError: /home/valar/Dokumenty/ERP_v1/db/seeds.rb:9: syntax error, unexpected ',', expecting => ...o.new(giver:Employee.create()), Kudo.new(receiver:Employee.c... ... /home/valar/Dokumenty/ERP_v1/db/seeds.rb:9: syntax error, unexpected ')', expecting end-of-input ...ew(receiver:Employee.create()) ... ... ... ^

第二种写法及错误

kudos = Kudo.create!(Title: Faker::Adjective.positive, Content: Faker::Company.bs, giver:Employee.create(), receiver:Employee.create())

报错信息:

rake aborted!
ActiveRecord::NotNullViolation: PG::NotNullViolation: ERROR: null value in column "giver_id" violates not-null constraint


模型与Schema信息

Employee模型

class Employee < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  has_many :given_kudos, class_name: 'Kudo', foreign_key: 'giver_id'
  has_many :received_kudos, class_name: 'Kudo', foreign_key: 'receiver_id'
end

Kudo模型

class Kudo < ApplicationRecord
  validates :Title, presence: true
  validates :Content, presence: true
  belongs_to :giver, class_name: 'Employee'
  belongs_to :receiver, class_name: 'Employee'
end

Schema文件

ActiveRecord::Schema.define(version: 2023_01_20_162230) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "employees", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.index ["email"], name: "index_employees_on_email", unique: true
    t.index ["reset_password_token"], name: "index_employees_on_reset_password_token", unique: true
  end

  create_table "kudos", force: :cascade do |t|
    t.string "Title", null: false
    t.text "Content", null: false
    t.integer "giver_id", null: false
    t.integer "receiver_id", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

end

修复方案

第一种写法的核心问题是语法错误:create!接收属性哈希,不能直接传入Kudo.new对象;第二种写法的问题是Faker可能生成重复邮箱,导致Employee创建失败,最终giver/receiver为nil,触发非空约束错误。

正确的种子文件写法如下:

# 先创建10个邮箱唯一的员工
employees = []
10.times do
  email = Faker::Internet.unique.email(domain: 'gmail.com')
  employees << Employee.create!(email: email, password: 'password')
end

# 生成20条Kudo,随机分配给不同员工
20.times do
  giver = employees.sample
  # 确保发送者和接收者不是同一人
  receiver = employees.reject { |e| e == giver }.sample
  
  Kudo.create!(
    Title: Faker::Adjective.positive,
    Content: Faker::Company.bs,
    giver: giver,
    receiver: receiver
  )
end

关键说明

  • 使用Faker::Internet.unique.email避免邮箱重复,保证Employee创建成功;
  • 从已创建的员工池中随机选取giver和receiver,避免动态创建员工时的潜在失败;
  • 通过reject过滤掉发送者自身,符合“不同用户间生成Kudo”的需求。

内容的提问来源于stack exchange,提问作者Wojtek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 01:10:26