gem 'activerecord', '4.0.0'
require 'active_record'
require 'minitest/autorun'
require 'logger'
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Base.establish_connection(
:adapter => 'postgresql',
:database => 'x'
)
ActiveRecord::Schema.define do
create_table :users, :force => true do |t|
end
create_table :companies, :force => true do |t|
end
create_table :participations, :force => true do |t|
t.integer :user_id
t.integer :company_id
end
end
class Company < ActiveRecord::Base
has_many :participations, :dependent => :destroy, :autosave => true
has_many :users, :through => :participations, :autosave => true
end
class Participation < ActiveRecord::Base
belongs_to :company
belongs_to :user
end
class User < ActiveRecord::Base
has_many :participations, :dependent => :destroy
has_many :companies, :through => :participations
end
class TestMe < MiniTest::Unit::TestCase
def test_dependent_destroy
c = Company.create!
u = User.create!
c.users << u
c.destroy
assert_equal [], Participation.all.to_a
assert_equal [], User.all.to_a
end
end
results in:
vim test.rb
-- create_table(:users, {:force=>true})
D, [2013-10-11T17:58:44.115600 #10524] DEBUG -- : (1.3ms) DROP TABLE "users"
D, [2013-10-11T17:58:44.117995 #10524] DEBUG -- : (2.2ms) CREATE TABLE "users" ("id" serial primary key)
-> 0.0186s
-- create_table(:companies, {:force=>true})
D, [2013-10-11T17:58:44.119492 #10524] DEBUG -- : (0.6ms) DROP TABLE "companies"
D, [2013-10-11T17:58:44.120835 #10524] DEBUG -- : (1.2ms) CREATE TABLE "companies" ("id" serial primary key)
-> 0.0028s
-- create_table(:participations, {:force=>true})
D, [2013-10-11T17:58:44.122231 #10524] DEBUG -- : (0.7ms) DROP TABLE "participations"
D, [2013-10-11T17:58:44.123865 #10524] DEBUG -- : (1.5ms) CREATE TABLE "participations" ("id" serial primary key, "user_id" integer, "company_id" integer)
-> 0.0030s
MiniTest::Unit::TestCase is now Minitest::Test. From tmp/test.rb:41:in `<main>'
Run options: --seed 47789
# Running:
D, [2013-10-11T17:58:44.162282 #10524] DEBUG -- : (0.2ms) BEGIN
D, [2013-10-11T17:58:44.167369 #10524] DEBUG -- : SQL (0.4ms) INSERT INTO "companies" DEFAULT VALUES RETURNING "id"
D, [2013-10-11T17:58:44.167786 #10524] DEBUG -- : (0.1ms) COMMIT
D, [2013-10-11T17:58:44.169482 #10524] DEBUG -- : (0.0ms) BEGIN
D, [2013-10-11T17:58:44.173068 #10524] DEBUG -- : SQL (0.5ms) INSERT INTO "users" DEFAULT VALUES RETURNING "id"
D, [2013-10-11T17:58:44.173411 #10524] DEBUG -- : (0.1ms) COMMIT
D, [2013-10-11T17:58:44.182291 #10524] DEBUG -- : (0.1ms) BEGIN
D, [2013-10-11T17:58:44.194695 #10524] DEBUG -- : SQL (2.8ms) INSERT INTO "participations" ("company_id", "user_id") VALUES ($1, $2) RETURNING "id" [["company_id", 1], ["user_id", 1]]
D, [2013-10-11T17:58:44.195175 #10524] DEBUG -- : (0.1ms) COMMIT
D, [2013-10-11T17:58:44.195378 #10524] DEBUG -- : (0.1ms) BEGIN
D, [2013-10-11T17:58:44.196501 #10524] DEBUG -- : Participation Load (0.5ms) SELECT "participations".* FROM "participations" WHERE "participations"."company_id" = $1 [["company_id", 1]]
D, [2013-10-11T17:58:44.198015 #10524] DEBUG -- : SQL (0.5ms) DELETE FROM "participations" WHERE "participations"."id" = $1 [["id", 1]]
D, [2013-10-11T17:58:44.198582 #10524] DEBUG -- : SQL (0.3ms) DELETE FROM "companies" WHERE "companies"."id" = $1 [["id", 1]]
D, [2013-10-11T17:58:44.198728 #10524] DEBUG -- : (0.1ms) COMMIT
D, [2013-10-11T17:58:44.199073 #10524] DEBUG -- : Participation Load (0.1ms) SELECT "participations".* FROM "participations"
D, [2013-10-11T17:58:44.199414 #10524] DEBUG -- : User Load (0.1ms) SELECT "users".* FROM "users"
F
Finished in 0.048269s, 20.7172 runs/s, 41.4345 assertions/s.
1) Failure:
TestMe#test_dependent_destroy [tmp/test.rb:48]:
Expected: []
Actual: [#<User id: 1>]
1 runs, 2 assertions, 1 failures, 0 errors, 0 skips
I don't see what is wrong with this? Your tests show that all the Participation (join records) are destroyed. For has_and_belongs_to_many
and has_many through
associations the associated records are never deleted/destroyed with dependent. As per the API documentation:
With has_and_belongs_to_many and has_many :through, if you want to delete the associated records themselves, you can always do something along the lines of person.tasks.each(&:destroy).
@dnagir : I think that this is a design problem. Applying the following diff to your gist makes it green:
--- bar.rb 2013-10-12 15:11:42.058069352 +0200
+++ foo.rb 2013-10-12 15:25:51.316801856 +0200
@@ -30,11 +32,11 @@
class Participation < ActiveRecord::Base
belongs_to :company
- belongs_to :user
+ belongs_to :user, dependent: :destroy
end
class User < ActiveRecord::Base
- has_many :participations, :dependent => :destroy
+ has_many :participations
has_many :companies, :through => :participations
end
@robin850 is right.
Thank you for reporting.
Most helpful comment
@dnagir : I think that this is a design problem. Applying the following diff to your gist makes it green: