Rails / ActiveRecord has_one association behavior when setting the child to "nil"

My colleagues and I noticed something about ActiveRecord associations has_onethat feel wrong / dangerous and don't seem to be documented easily.

Suppose we have this setting:

class User < ApplicationRecord
  has_one :subscription
end

class Subscription < ApplicationRecord
  belongs_to :user
end

Without "depend: destroy"

> user = User.create(name: "Bob")
> user.subscription = Subscription.create(provider: "Stripe")

> user.subscription = nil

   (0.1ms)  begin transaction
  SQL (0.4ms)  UPDATE "subscriptions" SET "user_id" = ?, "updated_at" = ? WHERE "subscriptions"."id" = ?  [["user_id", nil], ["updated_at", 2017-01-10 19:24:56 UTC], ["id", 2]]
   (2.0ms)  commit transaction

With "depend: destroy"

class User < ApplicationRecord
  has_one :subscription, dependent: :destroy
end


> user = User.create(name: "Bob")
> user.subscription = Subscription.create(provider: "Stripe")

> user.subscription = nil

   (0.1ms)  begin transaction
    SQL (1.1ms)  DELETE FROM "subscriptions" WHERE "subscriptions"."id" = ?  [["id", 1]]
   (0.7ms)  commit transaction

Is this the expected behavior? I am really surprised that an SQL call is made without any explicit call to saveeither destroyor or updateetc. I am also confused about why dependant: destroychanging behavior in this scenario.

Is this supposed, and if so, is it documented somewhere? The version dependant: destroyseems especially dangerous.

This has been tested with Rails 5, as well as several versions of Rails 4.

+4
2

?

. Rails docs has_one :

# = () ( .account_id = account.id; beneficiary.save)

dependent: :destroy, :

: destroy

, SQL DELETE.

0

guide:

4.2.5 ?

has_one, ( ). , , .

- , false, .

(, has_one), unsaved ( new_record? true), . .

has_one , association.build.

+2

Source: https://habr.com/ru/post/1666419/


All Articles