We have 2 simple models where a workspace
has many memberships
. We need to prevent the last membership
from being destroyed unless it's workspace
is destroyed.
This code isn't letting us destroy memberships when we destroy the workspace -- could someone tell me what I'm doing wrong or if there's a better way to do this?
class Workspace < ApplicationRecord
has_many :memberships, dependent: :destroy
end
class Membership < ApplicationRecord
belongs_to :workspace, counter_cache: true
before_destroy :ensure_one_member, unless: -> { workspace.destroyed? }
private
def ensure_one_member
raise "Can't delete the last member" if workspace.memberships.count == 1
end
end
% rails c
Loading development environment (Rails 7.0.2.2)
irb(main):001:0> Workspace.last.destroy
Workspace Load (0.6ms) SELECT "workspaces".* FROM "workspaces" ORDER BY "workspaces"."id" DESC LIMIT $1 [["LIMIT", 1]]
TRANSACTION (0.2ms) BEGIN
Membership Load (0.8ms) SELECT "memberships".* FROM "memberships" WHERE "memberships"."workspace_id" = $1 [["workspace_id", 3]]
Membership Count (0.6ms) SELECT COUNT(*) FROM "memberships" WHERE "memberships"."workspace_id" = $1 [["workspace_id", 3]]
TRANSACTION (0.2ms) ROLLBACK
/Users/vince/code/myapp/app/models/membership.rb:6:in `ensure_one_member': Can't delete the last member (RuntimeError)
CodePudding user response:
As fas as i know, rollback occurs because rails trying to delete Members
before Workspace
so ensure_one_member
still triggered even when you try to destroy Workspace
. It's not a perfect but destroyed_by_association
check may solve your problem. Youn can check related discussion here