从连接表中销毁嵌套资源

时间:2017-01-20 14:23:49

标签: ruby-on-rails activerecord

我有以下情况需要销毁与来自material

item_materials相关联的project个对象
begin
  require 'bundler/inline'
rescue LoadError => e
  $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler'
  raise e
end

gemfile(true) do
  source 'https://rubygems.org'
  gem 'rails', '4.2.7.1'
  gem 'sqlite3'
end

require 'active_record'
require 'minitest/autorun'
require 'logger'

Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)

ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :projects, force: true do |t|
  end

  create_table :items, force: true do |t|
    t.integer :project_id
  end

  create_table :materials, force: true do |t|
  end

  create_table :item_materials, force: true do |t|
    t.integer :item_id
    t.integer :material_id
  end
end

class Project < ActiveRecord::Base
  has_many :items, inverse_of: :project

  accepts_nested_attributes_for :items, allow_destroy: true

  def clean_up_items
    items.each do |item|
      item.item_materials.each do |item_material|
        item_material.mark_for_destruction
        item_material.material.mark_for_destruction
      end
    end

    save
  end
end

class Item < ActiveRecord::Base
  belongs_to :project, inverse_of: :items
  has_many :item_materials, dependent: :destroy, inverse_of: :item

  accepts_nested_attributes_for :item_materials, allow_destroy: true
end

class ItemMaterial < ActiveRecord::Base
  belongs_to :item, inverse_of: :item_materials
  belongs_to :material, inverse_of: :item_materials

  accepts_nested_attributes_for :material, allow_destroy: true
end

class Material < ActiveRecord::Base
  has_many :item_materials, dependent: :destroy, inverse_of: :material
end

class ProjectTest < Minitest::Test
  def test_destroy_item_material_and_material
    project = Project.create!
    item = Item.create! project: project
    material = Material.create!
    item_material = ItemMaterial.create! item: item, material: material

    assert project.reload.clean_up_items

    assert Project.find_by_id(project)
    assert Item.find_by_id(item)
    assert_nil ItemMaterial.find_by_id(item_material)
    assert_nil Material.find_by_id(material)
  end
end

有没有办法在不手动打开交易的情况下完成,只需设置正确的关联选项?

1 个答案:

答案 0 :(得分:0)

我认为这样做。

您只需要MaterialItemMaterial:through的正确关联。您需要更改关联才能使用class Project < ActiveRecord::Base has_many :items end class Item < ActiveRecord::Base belongs_to :project has_many :item_materials, dependent: :destroy has_many :materials, through: :item_materials end class Material < ActiveRecord::Base has_many :item_materials, dependent: :destroy has_many :items, through: :item_materials end class ItemMaterial < ActiveRecord::Base belongs_to :item belongs_to :material end

textOn