1

I am having a model Evaluation that has many sub evaluations (self refential)

class Evaluation < ApplicationRecord

  has_many :sub_evaluations, class_name: "Evaluation", foreign_key: "parent_id", dependent: :destroy

  before_save :calculate_score

  def calculate_score
    # do something
  end

end

I am creating and updating evaluation with sub evaluations as nested attributes.

calculate_score method is triggered on sub evaluation creation but not while updating. I have tried before_update and after_validation. But nothing seems to be working.

Evaluation form

= form_for @evaluation do |f|
  ...
  = f.fields_for :sub_evaluations do |sub_evaluation|
   ...

What seems to be the issue?

webster
  • 3,902
  • 6
  • 37
  • 59
  • Could you show how you are updating sub evaluations ? – Yogesh Khater Jul 28 '16 at 10:34
  • I'm not able to reproduce this. `before_save` is getting called for every child whose content is updated. One thing to check is if you have permitted `id` in `sub_evaluations_attributes` – Yogesh Khater Jul 28 '16 at 11:10
  • I have permitted id in sub_evaluations_attributes. I guess you are checking it in Rails 5. – webster Jul 28 '16 at 11:22
  • Yes, I'm checking it in Rails 5.0.0.beta3. – Yogesh Khater Jul 28 '16 at 11:31
  • Check if you are able to reproduce this on console using below steps, `evaluation = Evaluation.first` `sub_evaluation = evaluation.sub_evaluations.first` `sub_evaluation.any_attribute = 'any_value'` `evaluation.sub_evaluations = [sub_evaluation]` `evaluation.save` – Yogesh Khater Jul 28 '16 at 11:36
  • Yes I am able to reproduce it with an integer field on the console. B/w my rails version is 5.0.0.rc1 – webster Jul 28 '16 at 12:15
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/118541/discussion-between-rahul-and-yogesh-khater). – webster Jul 28 '16 at 12:20

1 Answers1

1

This article helped me to fix the issue.

Child callback isn't triggered because the parent isn't "dirty".

The solution in the article is to "force" it to be dirty by calling attr_name_will_change! on a parent attribute that, in fact, does not change.

Here is the updated model code:

class Evaluation < ApplicationRecord

  has_many :sub_evaluations, class_name: "Evaluation", foreign_key: "parent_id", dependent: :destroy

  before_save :calculate_score

  def calculate_score
    # do something
  end

  def exam_id= val
    exam_id_will_change!
    @exam_id = val
  end

end

See Active Model Dirty in the Rails API

webster
  • 3,902
  • 6
  • 37
  • 59