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
