首页 > 解决方案 > Rails 不保存引用 ID 以记录错误:“类必须存在”

问题描述

问题是我找不到为什么在创建新记录时无法插入参考列 ID。

我有 3 张表 shop_plan、shop 和 app

以下是表架构:

  create_table "shop_plans", force: :cascade do |t|
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "shops", force: :cascade do |t|
    t.string "url"
    t.bigint "plan_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["plan_id"], name: "index_shops_on_plan_id"
  end

  create_table "apps", force: :cascade do |t|
    t.bigint "shop_id"
    t.binint "amount"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["app_id"], name: "index_apps_on_shop_id"
  end

  add_foreign_key "shops", "shop_plans", column: "plan_id"
  add_foreign_key "apps", "shops"

下面是模型

class ShopPlan < ApplicationRecord
  has_many :shop
end

class Shop < ApplicationRecord
  belongs_to :shop_plan, class_name: 'ShopPlan', foreign_key: :plan_id
  has_many :app
end

class App < ApplicationRecord
  belongs_to :shop, class_name: 'Shop', foreign_key: :shop_id
end

将在seed.db 中为表shop_plan 添加1 条默认记录

ShopPlan.create(name: 'Basic')

ShopPlanShopplan_id列链接Shop

商店应用程序shop_id列链接App

我在用户访问索引时预先插入了一些值:

#basic_plan
@basicPlan = ShopPlan.where(name: "Basic").first

# if new shop registered, add to database
unless Shop.where(url: @shop_session.url).any?
  shop = Shop.new
  shop.url = @shop_session.url
  shop.plan_id = @basicPlan.id

  shop.save
end

但是,当我运行第二次插入时,此插入效果很好:

@shop= Shop.where(url: @shop_session.url).first
    unless App.where(shop_id: @shop.id).any?
      app = App.new
      app.shop_id = @shop.id,
      app.amount = 10
      app.save
    end

发生错误,因为不知何故app.shop_id不会添加到我的@shop.id,它会返回错误:{"shop":["must exist"]}

我什至尝试硬编码app.shop_id =1,但它没有帮助,当我添加optional: true到 app.db 模型时,它会插入null

感谢是否有人可以帮助指出我收到此错误的原因

编辑:@arieljuod 要明确 1)由于介于ShopAnd之间Shop_Plan,我必须指定确切的列类,我使用的是手册plan_id而不是使用默认shopplans_id列。2)我在 App 内更新了 1 列,除非只是在调试时进行检查。

标签: ruby-on-railsshopify

解决方案


首先,就像@David 指出的那样,您的关联名称不正确。您必须进行设置has_many :shopshas_many :apps因此 activerecord 知道如何找到正确的类。

其次,如果可以从关联名称中推断出类,则不必指定class_name选项,因此可以是belongs_to :shopand belongs_to :shop_plan, foreign_key: :plan_id。它适用于您的设置,只是建议删除不必要的代码。

现在,对于您的关系,我认为您不应该first any? new手动执行这些块,rails 可以为您处理这些块。

你可以做类似的事情

@basicPlan = ShopPlan.find_by(name: "Basic")

#this gives you the first record or creates a new one
@shop = @basicPlan.shops.where(url: @shop_session.url).first_or_create 

#this will return the "app" of the shop if it already exists, and, if nil, it will create a new one
@app = @shop.app or @shop.create_app

推荐阅读