2

I have two models with many-to-many association through third model. By ex:

class Physician < ActiveRecord::Base
  has_many :appointments
  has_many :patients, through: :appointments
end

class Appointment < ActiveRecord::Base
  belongs_to :physician
  belongs_to :patient
end

class Patient < ActiveRecord::Base
  has_many :appointments
  has_many :physicians, through: :appointments
end

And using simple_form i have this checkbox set (Physician form):

...
= f.association :patients, as: :check_boxes
...

When i check some checkboxes, after save rails will create appointments in database.

When i uncheck checkboxes, rails will destroy some unchecked appointments.

So update will be eq to

physician.patient_ids = []

I want to validate appointments before delete. By example if appointments have some warnings, i want to show alert validation error on saving Physician form.

So, i thought, maybe rails will call destroy method on appointments, and tried:

class Appointment < ActiveRecord::Base

before_destroy :check_destroy
private
def check_destroy
  raise 'you can not do it!'
end

Nope, rails just removed appointments from database on save Physician.

Maybe rails will use delete method? Then i tried this one:

  class Appointment < ActiveRecord::Base
  def delete
    raise 'you can not do it!'
  end

Nope, again.

Seems to rails just remove join-association (appointment) straight from database.

How to prevent it? I want to validate all appointments that will be deleted before saving Physician, and add error to Physician if some appointments can not be deleted.

  • Do any of the methods in the following post work? http://stackoverflow.com/questions/123078/how-do-i-validate-on-destroy-in-rails – rodamn Sep 08 '15 at 23:12
  • @rodamn if i call destroy on Physician, i think it will works by dependent: :destroy. But in my case, i don't calling destroy, but just calling save on model in controller #update action with set of ids. – Andrey Skuratovsky Sep 08 '15 at 23:19

1 Answers1

4

From the rails documentation

Similar to the normal callbacks that hook into the life cycle of an Active Record object, you can also define callbacks that get triggered when you add an object to or remove an object from an association collection.

Example from Docs

class Project
  has_and_belongs_to_many :developers, after_add: :evaluate_velocity

  def evaluate_velocity(developer)
    ...
  end
end

So in your particular scenario try

  has_many :patients, through: :appointments, before_remove :check_remove
pshoukry
  • 755
  • 5
  • 14