更新时Rails多级关系被破坏

时间:2017-07-31 09:06:27

标签: ruby-on-rails ruby activerecord foreign-keys ruby-on-rails-5

我有一个四级深度模型结构:Domain>主题>装置>属性

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

1 个答案:

答案 0 :(得分:1)

  

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

继续使用您的模型,您的Device模型存在缺陷。您belongs_to :device内有Device。也许你应该按照协会belongs_to :subject。这可能会导致您当前的问题。尝试更改Device模型,如此

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