【问题标题】:Rails multi-level relation destroyed when updatingRails 多级关系在更新时被破坏
【发布时间】: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_idid 参数。 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


【解决方案1】:

当从 Subject 模型中删除 has_many: :devices 时,一切 按预期工作。

继续使用您的模型,您的 Device 模型有缺陷。 Device 内有 belongs_to :device。也许您应该根据协会拥有belongs_to :subject。这可能会导致您当前的问题。尝试像这样更改Device 模型

class Device < ApplicationRecord 
  has_many :properties
  belongs_to: :subject
end

【讨论】:

  • Device 模型中的缺陷是拼写错误...代码实际上如您所描述,即您的建议没有解决问题,遗憾的是更新了问题描述。
  • @KevinvandenBekerom 好的。向我们展示您如何更新主题。必要的代码和日志应该会有所帮助
猜你喜欢
  • 2013-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多