Altering an associated model using a before_validation callback

377 views Asked by At

I am struggling a little with how to implement a Rails callback correctly:

I have a model X (with attributes A, B and C) with a has_many relationship to model Y (with attributes C, D and E - i.e. both have the attribute C). I have a model validation on X that states that attribute C of all associated model Ys must match that of model X.

Therefore on modifying the C attribute during an update of model X, I have used a 'before_validation, on :update' callback to first change the C value on all associated Y models to match that of the updated C value on model X. This allows model X to validate and update fine. However, the modified C values on the associated model Ys do not stick and revert back to their original values upon model X reload.

So do I need to also have an 'after_save' callback to now 'lock in' the model Y changes? Or should I be using a different method for doing this sort of thing?

----- Update ------------

I think I'm maybe saving to the database incorrectly:

My callback code

class X
  ....
  before_validation :update_Ys, on: :update
  ....
  def update_Ys
    self.Ys.each do |k|
      k['C'] = self.C 
      k.save
    end
  end
2

There are 2 answers

0
GerryDevine On

What I ended up doing was having two callbacks

Firstly, a 'before_validation, on :update' where

def update_Ys
  self.Ys.each do |k|
    k['C'] = self.C 
  end
end

which allowed validation of model X to go through

and then an 'after_save' where I hit the database directly with a save on the updated model Ys. I'm guessing this is not the best way to do this so if anyone has advice on how to improve this please let me know.

2
henrymason On

You need to add a before_save callback on your model X. and then check if it has a changed attribute C. if it has you will need to apply all the logic to update your model Y accordingly in that call back.