Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 5 before_destroy throw(:abort)

I'm working in a legacy Rails app that has been diligently upgraded with each major version of Rails and we're currently on rails 5.1 and I can't get a before_destroy to prevent the deletion if it fails a validation

I've been reading that return false has been deprecated and we're all supposed to use throw :abort but neither are working. I'm not getting any errors, the join record just gets deleted despite the throw

user.rb:

class User < ApplicationRecord
  has_many :permission_users
  has_many :permissions, through: :permission_users, dependent: :destroy
end

join model permission_user.rb:

class PermissionUser < ApplicationRecord
  belongs_to :user
  belongs_to :permission

  before_destroy :check_before_removing!

  private

  def check_before_removing!
    if not_valid? # condition isn't important
      errors.add :base, exception.message
      throw(:abort)
    end
  end
end

my spec:

specify "cannot have their admin permissions revoked" do
  expect {
    admin.permissions.delete admin_permission
  }.to change { admin.permissions.count }.by(0)       
end

# => expected `admin.permissions.count` to have changed by 0, but was changed by -1
like image 436
Sparkmasterflex Avatar asked Jun 28 '18 02:06

Sparkmasterflex


2 Answers

There's a catch with this callback:

before_destroy callbacks should be placed before dependent: :destroy associations (or use the prepend: true option), to ensure they execute before the records are deleted by dependent: :destroy.

So please try

before_destroy :check_before_removing!, prepend: true
like image 154
Grzegorz Avatar answered Nov 10 '22 19:11

Grzegorz


try to do something like this

before_destroy :check_before_removing, prepend: true

def check_before_removing if true && some_condition throw(:abort) end end

like image 4
Hatemii Avatar answered Nov 10 '22 21:11

Hatemii