【发布时间】:2018-01-06 18:34:55
【问题描述】:
我有一个四级深度模型结构:域 > 主题 > 设备 > 属性
class Domain < ApplicationRecord
has_many :subjects
end
class Subject < ApplicationRecord
has_many :devices
belongs_to: :domain
end
class Device < ApplicationRecord
has_many :properties
belongs_to: :subject
end
class Property < ApplicationRecord
belongs_to :device
end
控制器代码
def update
result = @subject.update(parameters)
if result
render json: @subject
else
render_errors(@subject.errors)
end
end
@subject 被检索为之前的操作,通过从域开始查询模型树,分别使用域和主题的 domain_id 和 id 参数。 parameters 只是参数的散列,例如{name: :new_name}
更新主题时,与域的关系丢失,即domain_id 被 rails 设置为 NUL。结果,主题下方的整个模型树也将与父域断开连接。
从主题模型中删除has_many: :devices 时,一切都按预期工作。我只想更新一个主题并保留与父域的关系。我将如何使用上述模型实现这一目标?
编辑 1 - 添加了两种情况的日志。
使用完整的关系模型记录(导致错误)
Domain Load (0.5ms) SELECT "domains".* FROM "domains" WHERE "domains"."name" = ? LIMIT ? [["name", "Manatree"], ["LIMIT", 1]]
CACHE (0.0ms) SELECT "domains".* FROM "domains" WHERE "domains"."name" = ? LIMIT ? [["name", "Manatree"], ["LIMIT", 1]]
Subject Load (0.0ms) SELECT "subjects".* FROM "subjects" WHERE "subjects"."domain_id" = ? AND "subjects"."name" = ? LIMIT ? [["domain_id", 3], ["name", "s1"], ["LIMIT", 1]]
Subject Load (0.5ms) SELECT "subjects".* FROM "subjects" WHERE "subjects"."id" = ? LIMIT ? [["id", 5], ["LIMIT", 1]]
(0.0ms) begin transaction
Domain Load (0.0ms) SELECT "domains".* FROM "domains" WHERE "domains"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]]
SQL (7.1ms) UPDATE "subjects" SET "domain_id" = NULL WHERE "subjects"."domain_id" = ? AND "subjects"."id" = 5 [["domain_id", 3]]
Subject Exists (0.0ms) SELECT 1 AS one FROM "subjects" WHERE "subjects"."domain_id" = ? AND "subjects"."name" = ? LIMIT ? [["domain_id", 3], ["name", "s2"], ["LIMIT", 1]]
SQL (1.0ms) UPDATE "subjects" SET "name" = ?, "updated_at" = ? WHERE "subjects"."id" = ? [["name", "s2"], ["updated_at", "2017-07-31 08:46:38.171240"], ["id", 5]]
(7.5ms) commit transaction
Subject Load (0.0ms) SELECT "subjects".* FROM "subjects"
Completed 200 OK in 30ms (Views: 0.5ms | ActiveRecord: 16.6ms)
从主题模型中删除belongs_to: :devices 时的日志
Domain Load (0.0ms) SELECT "domains".* FROM "domains" WHERE "domains"."name" = ? LIMIT ? [["name", "Manatree"], ["LIMIT", 1]]
CACHE (0.0ms) SELECT "domains".* FROM "domains" WHERE "domains"."name" = ? LIMIT ? [["name", "Manatree"], ["LIMIT", 1]]
Subject Load (0.5ms) SELECT "subjects".* FROM "subjects" WHERE "subjects"."domain_id" = ? AND "subjects"."name" = ? LIMIT ? [["domain_id", 3], ["name", "s3"], ["LIMIT", 1]]
Subject Load (0.5ms) SELECT "subjects".* FROM "subjects" WHERE "subjects"."id" = ? LIMIT ? [["id", 6], ["LIMIT", 1]]
(0.0ms) begin transaction
Domain Load (0.5ms) SELECT "domains".* FROM "domains" WHERE "domains"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]]
SQL (6.5ms) UPDATE "subjects" SET "name" = ?, "updated_at" = ? WHERE "subjects"."id" = ? [["name", "s4"], ["updated_at", "2017-07-31 08:48:57.962218"], ["id", 6]]
(7.0ms) commit transaction
Subject Load (0.0ms) SELECT "subjects".* FROM "subjects"
Completed 200 OK in 25ms (Views: 0.4ms | ActiveRecord: 15.1ms)
编辑 2 - 种子数据可能有问题...
domainA = Domain.create(name: :company)
s1 = domainA.subjects.create(name: :subject)
# domainA.save
d1 = s1.devices.create(name: :device)
# s1.save
p1 = d1.properties.create(name: :prop1, property_type: :double, value: 10.0)
p2 = d1.properties.create(name: :prop2, property_type: :string, value: :on)
p3 = d1.properties.create(name: :prop3, property_type: :string, value: :Lamp)
# d1.save
domainA.save
【问题讨论】:
-
在 Rails 控制台中保存主题实例时会发生这种情况吗?
-
为什么
domain_id被设置为nil?您要发送什么参数,SubjectsController在做什么(假设您正在谈论的错误来自控制器操作)?我根本看不出删除has_many :devices应该如何影响这种行为。您可以尝试提供minimal reproducible example吗? -
parameters是一种方法吗?如果是这样,请向我们展示该代码。生成的日志也应该有所帮助。 -
@Pavan 我排除了参数是罪魁祸首。实际上,我在更新方法中硬编码了一个有效的参数哈希 -->
@subject.update({name: :non_existing_new_name})。尽管如此,错误仍然存在...... -
你应该使用强参数。我还是想看看你的日志。你能告诉我们吗?
标签: ruby-on-rails ruby activerecord foreign-keys ruby-on-rails-5