问题是我找不到创建新记录时为什么不能插入参考列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')
ShopPlan 和 Shop 通过plan_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)由于Shop
和Shop_Plan
之间的关系,我必须使用特定的确切列类,我使用的是手动plan_id
而不是默认的shopplans_id
列。
2)我在App内更新了1列,所有这些都除非在调试时进行检查。
答案 0 :(得分:1)
首先,就像@David指出的那样,您的关联名称不正确。您必须设置has_many :shops
和has_many :apps
,以便activerecord知道如何找到正确的类。
第二,如果可以从关联名称推断出类,则不必指定class_name
选项,因此可以是belongs_to :shop
和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
答案 1 :(得分:0)
我发现了我的代码无法正常工作的愚蠢原因。
这不是因为as_many :shops
和has_many :app
,也不是因为我在创建记录时的代码。
在app.shop_id = @shop.id,
的App中创建新记录时,这是由于愚蠢的逗号',因为我一直在Ruby和JavaScript之间切换。谢谢@arieljuod和@David的努力