Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix regression setting children record in parent before_save callback. #33673

Conversation

tgxworld
Copy link
Contributor

While upgrading Discourse to Rails 5.2.1, one of our model's spec started to fail and it turns out it was due to d7a3f33 which was merged in #32952.

cc @kamipo @mechanicles

@rails-bot
Copy link

r? @georgeclaghorn

(@rails-bot has picked a reviewer for you, use r? to override)

@tgxworld
Copy link
Contributor Author

r? @kamipo

@rails-bot rails-bot assigned kamipo and unassigned georgeclaghorn Aug 21, 2018
valid = association_valid?(reflection, record, index)
saved = valid ? association.insert_record(record, false) : false
association_valid?(reflection, record, index)
record.errors.delete(reflection.foreign_key)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems wrong. Why would rails remove an error of a validation added by itself? If there is an error we should not save. If this is the behavior we want we should not add this error at the first place, not remove it after it added.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point 👍

association.insert_record(record, false)
else
false
end
else
association.insert_record(record)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kamipo should not this set saved?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least I think should not set saved here for stable version.

Before #32796, autosaving associated collections always don't care about whether saving collections would be succeeded or not.
The else branch keeps the original behavior when the association validate: false is given explicitly.

@tgxworld tgxworld force-pushed the regression_setting_children_record_in_parent_before_save branch 2 times, most recently from aa87222 to 3b7d032 Compare August 22, 2018 01:26
@tgxworld
Copy link
Contributor Author

@rafaelfranca @kamipo Updated :)

else
association.insert_record(record)
if !association_saved
association_valid?(reflection, record, nil, false)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about just using errors.add(reflection.name)?
The record in this context is, not destroyed, not marked_for_destruction?, not reflection.options[:autosave] given.

diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb
index a405f05e0b..ed71e68ad1 100644
--- a/activerecord/lib/active_record/autosave_association.rb
+++ b/activerecord/lib/active_record/autosave_association.rb
@@ -392,7 +392,7 @@ def save_collection_association(reflection)
               records -= records_to_destroy
             end
 
-            records.each_with_index do |record, index|
+            records.each do |record|
               next if record.destroyed?
 
               saved = true
@@ -402,8 +402,8 @@ def save_collection_association(reflection)
                   saved = association.insert_record(record, false)
                 elsif !reflection.nested?
                   if reflection.validate?
-                    valid = association_valid?(reflection, record, index)
-                    saved = valid ? association.insert_record(record, false) : false
+                    saved = association.insert_record(record)
+                    errors.add(reflection.name) unless saved
                   else
                     association.insert_record(record)
                   end

@tgxworld tgxworld force-pushed the regression_setting_children_record_in_parent_before_save branch from 3b7d032 to bbcca44 Compare September 1, 2018 00:46
@tgxworld tgxworld force-pushed the regression_setting_children_record_in_parent_before_save branch from bbcca44 to 90240f6 Compare September 3, 2018 05:35
@tgxworld
Copy link
Contributor Author

tgxworld commented Sep 3, 2018

@kamipo Thank you for the review 👍 I've updated the code as per your comments.

@kamipo kamipo merged commit c810846 into rails:master Sep 3, 2018
@kamipo
Copy link
Member

kamipo commented Sep 3, 2018

Thanks!

kamipo added a commit that referenced this pull request Sep 3, 2018
…ecord_in_parent_before_save

Fix regression setting children record in parent before_save callback.
@tgxworld tgxworld deleted the regression_setting_children_record_in_parent_before_save branch September 3, 2018 07:39
@tgxworld
Copy link
Contributor Author

tgxworld commented Sep 3, 2018

Thank you again @kamipo 👍

@tgxworld
Copy link
Contributor Author

tgxworld commented Sep 3, 2018

@kamipo By the way, do you want me to backport this to Rails 5.2 stable?

@kamipo
Copy link
Member

kamipo commented Sep 3, 2018

I've already backported in 3a2e893.

@tgxworld
Copy link
Contributor Author

tgxworld commented Sep 3, 2018

Awesome!

tbrisker added a commit to tbrisker/foreman that referenced this pull request Nov 11, 2019
Due to a change in Rails (rails/rails#33673),
when factory bot creates a smart proxy with child hosts it now triggers
a save on the hosts, which in this test fails because hosts validate
that they have an environment set if they have a puppet proxy assigned.
mmoll pushed a commit to theforeman/foreman that referenced this pull request Nov 11, 2019
Due to a change in Rails (rails/rails#33673),
when factory bot creates a smart proxy with child hosts it now triggers
a save on the hosts, which in this test fails because hosts validate
that they have an environment set if they have a puppet proxy assigned.
eLvErDe pushed a commit to EarthLab-Luxembourg/foreman that referenced this pull request Nov 20, 2019
Due to a change in Rails (rails/rails#33673),
when factory bot creates a smart proxy with child hosts it now triggers
a save on the hosts, which in this test fails because hosts validate
that they have an environment set if they have a puppet proxy assigned.
eLvErDe pushed a commit to EarthLab-Luxembourg/foreman that referenced this pull request Nov 20, 2019
Due to a change in Rails (rails/rails#33673),
when factory bot creates a smart proxy with child hosts it now triggers
a save on the hosts, which in this test fails because hosts validate
that they have an environment set if they have a puppet proxy assigned.
ofedoren pushed a commit to ofedoren/foreman that referenced this pull request Nov 20, 2019
Due to a change in Rails (rails/rails#33673),
when factory bot creates a smart proxy with child hosts it now triggers
a save on the hosts, which in this test fails because hosts validate
that they have an environment set if they have a puppet proxy assigned.
Hamms added a commit to code-dot-org/code-dot-org that referenced this pull request Nov 4, 2020
It's not 100% clear why this is necessary, but here's what we do know:

- rails/rails#33673 changed something about the way child records are persisted when created as a part of their parents.
- Regional Partner Mappings should be unique, and this Regional Parter was invalid as created, because a Regional Partner for Alabama already exists in our test database as a result of seeding.
- On Rails 5.2, attempting to join sessions to workshops with `regional_partner.pd_workshops.joins(:sessions` fails when `regional_parter` is invalid.

Like I said, it's not entirely clear why these things are connected but a `git bisect` indicates that they are. A simple - if uninformed - fix is to simply not use a regional partner mapping here when that's not what we are actually testing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants