【问题标题】:Ruby on Rails has_many :through destroying more than it shouldRuby on Rails has_many :通过破坏超出其应有的范围
【发布时间】:2014-07-26 03:34:48
【问题描述】:

我正在创建一个应用程序,其中包含三个主要模型以及它们之间的关系,我需要跟踪一些属性:

schema.rb

  create_table "entities", force: true do |t|
    t.string   "name"
    t.string   "label"
    t.string   "img"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "entities", ["name"], name: "index_entities_on_name", unique: true, using: :btree

  create_table "entity_group_relationships", force: true do |t|
    t.integer  "entity_id"
    t.integer  "group_id"
    t.integer  "order"
    t.string   "label"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "entity_group_relationships", ["entity_id", "group_id"], name: "index_entity_group_relationships_on_entity_id_and_group_id", unique: true, using: :btree

  create_table "entity_property_relationships", force: true do |t|
    t.integer  "entity_id"
    t.integer  "property_id"
    t.integer  "group_id"
    t.integer  "order"
    t.string   "label"
    t.string   "value"
    t.integer  "visibility"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "group_property_relationships", force: true do |t|
    t.integer  "group_id"
    t.integer  "property_id"
    t.integer  "order"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "group_property_relationships", ["group_id", "property_id"], name: "index_group_property_relationships_on_group_id_and_property_id", unique: true, using: :btree
  add_index "group_property_relationships", ["group_id"], name: "index_group_property_relationships_on_group_id", using: :btree
  add_index "group_property_relationships", ["property_id"], name: "index_group_property_relationships_on_property_id", using: :btree

  create_table "groups", force: true do |t|
    t.string   "name"
    t.string   "default_label"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "groups", ["name"], name: "index_groups_on_name", unique: true, using: :btree

  create_table "properties", force: true do |t|
    t.string   "name"
    t.string   "units"
    t.string   "units_short"
    t.string   "default_label"
    t.string   "default_value"
    t.integer  "default_visibility"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "properties", ["name"], name: "index_properties_on_name", unique: true, using: :btree

Entity.rb

class Entity < ActiveRecord::Base
  has_many :entity_property_relationships
  has_many :entity_group_relationships
  has_many :properties, 
    through: :entity_property_relationships, 
    inverse_of: :entities
  has_many :groups, 
    through: :entity_group_relationships, 
    inverse_of: :entities
  validates :name, 
    presence: true
  #rest omitted
end

属性.rb

class Property < ActiveRecord::Base
  has_many :group_property_relationships
  has_many :entity_property_relationships
  has_many :entities, 
    through: :entity_property_relationships, 
    inverse_of: :properties
  has_many :groups, 
    through: :group_property_relationships, 
    inverse_of: :properties
  validates :name, presence: true
  #rest omitted
end

Group.rb

class Group < ActiveRecord::Base
  has_many :group_property_relationships
  has_many :entity_group_relationships
  has_many :entities, 
    through: :entity_group_relationships, 
    inverse_of: :groups
  has_many :properties, 
    through: :group_property_relationships, 
    inverse_of: :groups
  validates :name, 
    presence: true
  #rest omitted
end

entity_property_relationship.rb

class EntityPropertyRelationship < ActiveRecord::Base
  belongs_to :entity
  belongs_to :property
  validates :entity_id, 
    presence: true
  validates :property_id, 
    presence: true
  validates :order, 
    presence: :true
  #rest omitted
end

entity_group_relationship.rb

class EntityGroupRelationship < ActiveRecord::Base
  belongs_to :entity
  belongs_to :group 
  validates :entity_id, 
    presence: true
  validates :group_id, 
    presence: true
  validates :order, 
    presence: true
  #rest omitted
end

group_property_relationship.rb

class GroupPropertyRelationship < ActiveRecord::Base
  belongs_to :group
  belongs_to :property
  validates :group_id, 
    presence: true
  validates :property_id, 
    presence: true
  validates :order, 
    presence: true
  #rest omitted
end

问题

我试图阻止正在发生的行为是,当 property 被删除时,共享相同 EntityGroup 的所有 EntityPropertyRelationships 也会被删除。 GroupPropertyRelationshipsEntityGroupRelationships 的情况并非如此,从我所看到和理解的所有内容来看,这些关系已设置为具有相同的行为。

我正在使用 rspec 进行测试,这里有一些测试。

测试 1:

  it "should still own non-destroyed properties" do
    @entity = Entity.create!(name: "entity")

    @property1 = Property.create!(name: "property1")
    @property2 = Property.create!(name: "property2")

    @group = Group.create!(name: "group")
    @group.own!(@property1)
    @group.own!(@property2)

    @entity.own!(@group)

    @entity.utilizes?(@property1).should eq(true)
    @entity.utilizes?(@property2).should eq(true)

    @property1.destroy

    @entity.utilizes?(@property1).should eq(false)
    @entity.utilizes?(@property2).should eq(true)

    @group.owns?(@property1).should eq(false)
    @group.owns?(@property2).should eq(true)
  end

测试 1 是失败的测试。 entity 仍应为utilize property - utilizes?() 检查EntityPropertyRelationship 是否存在于entity 和给定的property 之间

测试 2

  it "should still own non-destroyed groups" do
    @entity = Entity.create!(name: "entity")

    @group1 = Group.create!(name: "group1")
    @group2 = Group.create!(name: "group2")

    @entity.own!(@group1)
    @entity.own!(@group2)

    @entity.owns?(@group1).should eq(true)
    @entity.owns?(@group2).should eq(true)

    @group1.destroy

    @entity.owns?(@group1).should eq(false)
    @entity.owns?(@group2).should eq(true)
  end

测试 3

  it "should still utilize non-destroyed groups' properties" do
    @entity = Entity.create!(name: "entity")

    @group1 = Group.create!(name: "group1")
    @group2 = Group.create!(name: "group2")

    @property1 = Property.create!(name: "property1")
    @property2 = Property.create!(name: "property2")

    @group1.own!(@property1)
    @group2.own!(@property2)

    @entity.own!(@group1)
    @entity.own!(@group2)

    @entity.owns?(@group1).should eq(true)
    @entity.owns?(@group2).should eq(true)
    @entity.utilizes?(@property1).should eq(true)
    @entity.utilizes?(@property2).should eq(true)

    @group1.destroy

    @entity.owns?(@group1).should eq(false)
    @entity.owns?(@group2).should eq(true)
    @entity.utilizes?(@property1).should eq(false)
    @entity.utilizes?(@property2).should eq(true)
  end

测试 2 和测试 3 通过正常。我似乎无法确定这些关系需要调用销毁每个EntityPropertyRelationship,即使property_id 不是最初被销毁的属性的ID。有什么我需要改变关系的地方吗,或者有什么方法可以通过 destroy_callbacks 防止这种情况发生?

【问题讨论】:

  • 您确定在测试 1 中删除了所有 EntityPropertyRelationship 记录吗?
  • 它不会销毁所有EntityPropertyRelationships (EPRs),它会销毁所有EPRs,其中entity_idgroup_idEPR 相同与正在销毁的property 相关联。 IE。 entity 通过group1property3property4 通过group2 具有属性property1property2。如果property1 被破坏,那么entity & property1entity & property2 之间的关系将被破坏,但property3 & property4 之间的关系保持不变。

标签: ruby-on-rails rspec has-many-through destroy


【解决方案1】:

哎哟!我刚刚发现了问题。我从没想过它会在哪里,这就是为什么花了这么长时间才找到的原因。在我的GroupPropertyRelationships 中,我有一个after_destroy,它会破坏每个Group's 关联的EntitiesEntityPropertyRelationships。它应该只是销毁EntityPropertyRelationships,其中group_idproperty_id 与当前被销毁的GroupPropertyRelationship 相同。我将GroupPropertyRelationshipafter_destroy 代码替换为:

after_destroy do |r|
  EntityPropertyRelationship.destroy_all group_id: r.group_id, property_id: r.property_id
end 

那一定是复制粘贴错误。

【讨论】:

    猜你喜欢
    • 2012-06-20
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-09
    • 1970-01-01
    • 2012-01-14
    相关资源
    最近更新 更多