This blog is part of our Rails 6.1 series.
In Rails 6.1, Rails will enqueue a background job to
destroy associated records if dependent: :destroy_async
is setup.
Let’s consider the following example.
class Team < ApplicationRecord
has_many :players, dependent: :destroy_async
end
class Player < ApplicationRecord
belongs_to :team
end
Now, if we call destroy method on an instance of
class Team Rails would enqueue an asynchronous job to delete the
associated players records.
We can verify this asynchronous job with a following test case.
class TeamTest < ActiveSupport::TestCase
include ActiveJob::TestHelper
test "destroying a record destroys the associations using a background job" do
team = Team.create!(name: "Portugal", manager: "Fernando Santos")
player1 = Player.new(name: "Bernardo Silva")
player2 = Player.new(name: "Diogo Jota")
team.players << [player1, player2]
team.save!
team.destroy
assert_enqueued_jobs 1
assert_difference -> { Player.count }, -2 do
perform_enqueued_jobs
end
end
end
Finished in 0.232213s, 4.3064 runs/s, 8.6128 assertions/s.
1 runs, 2 assertions, 0 failures, 0 errors, 0 skips
Alternatively, this enqueue behavior can also be demonstrated in rails console.
irb(main):011:0> team.destroy
TRANSACTION (0.1ms) begin transaction
Player Load (0.6ms) SELECT "players".* FROM "players" WHERE "players"."team_id" = ? [["team_id", 6]]
Enqueued ActiveRecord::DestroyAssociationAsyncJob (Job ID: 4df07c2d-f55b-48c9-8c20-545b086adca2) to Async(active_record_destroy) with arguments: {:owner_model_name=>"Team", :owner_id=>6, :association_class=>"Player", :association_ids=>[1, 2], :association_primary_key_column=>:id, :ensuring_owner_was_method=>nil}
Performed ActiveRecord::DestroyAssociationAsyncJob (Job ID: 4df07c2d-f55b-48c9-8c20-545b086adca2) from Async(active_record_destroy) in 34.5ms
Check out the
pull request
for more details.