Confirm before destruction

I have three classes: School , Account and Administratorship .

School

 has_many :administatorships has_many :administrators, :through => :administratorships 

Account

 has_many :administratorships 

Administratorship

 belongs_to :account belongs_to :school before_destroy :confirm_presence_of_alternate_administratorship_in_school protected def confirm_presence_of_alternate_administratorship_in_school unless school.administrators.count(["administratorships.account_id != #{id}"]) > 0 errors.add_to_base "The school must have at least one administrator" end end 

Now I would like for me to call the destroy command on the Administratorship instance so that it adds an error to the model and prevents the model from breaking. I removed the unless to see if this prevents the error from being added, but it isnโ€™t. It seems that the presence of errors in the model does not prevent destruction.

So my question is, is there a way to prevent destruction with checks? I understand that I could define a method that destroys only if the above condition is met, but it seems that the validation approach is a more elegant solution.

+49
validation ruby-on-rails
Apr 02 2018-11-11T00:
source share
4 answers

If you return false from this before_destroy method, this will prevent destruction.

+64
Apr 02 2018-11-11T00:
source share

This is Rails 5's answer, if you return false, it will give a warning about the failure: "Returning false in Active Record and Active Model callbacks will not implicitly stop the callback chain in Rails 5.1."

 def confirm_presence_of_alternate_administratorship_in_school return if school.administrators.count(["administratorships.account_id != #{id}"]) > 0 errors[:base] << 'The school must have at least one administrator' throw :abort end 
+17
Mar 24 '17 at 18:07
source share

Returning false from your validation method will prevent the destruction of the record.

Example:

 def confirm_presence_of_alternate_administratorship_in_school unless school.administrators.count(["administratorships.account_id != #{id}"]) > 0 # errors.add_to_base() is deprecated in Rails 3. Instead do... errors.add(:base, "The school must have at least one administrator") # this will prevent the object from getting destroyed return false end end 

Side Note: I am having trouble displaying this error message. Validation will work and the object will not be deleted, but there would be no message letting me know what happened. The reason for this was that the controller was redirected to the index instead of rendering the delete view (if there is an error creating a new user, for example, it will look like this: action => 'new'. In this case, there is no delete view). When this happened, the instance variable on which the error message was set (in error.add (: base, "message")) is actually reset, which destroys the error in this process.

+15
Jan 06 2018-12-01T00:
source share

I ended up using the code to create a can_destroy override on activerecord: https://gist.github.com/andhapp/1761098

 class ActiveRecord::Base def can_destroy? self.class.reflect_on_all_associations.all? do |assoc| assoc.options[:dependent] != :restrict || (assoc.macro == :has_one && self.send(assoc.name).nil?) || (assoc.macro == :has_many && self.send(assoc.name).empty?) end end end 

This has an additional advantage: make it trivial to hide / show the delete button on ui

+1
09 Oct '14 at 20:46
source share



All Articles