-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
Move convert_to_model
call from form_for
into form_with
#44468
Conversation
form_with
: Attempt to call to_model on model:
c337d32
to
ea1ea3f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you describe a bit the breaking change?
If I understand correctly, an object needs to implements to_model
to cause a change in behavior. If it does implement it and returns self like described in the docs, there's no change with this PR.
If the object implements to_model
, but points to another object that conforms to the Active Model API, the form is broken in the sense that it will use the object for the action
attribute, but the form's method
will use the passed object persisted?
(allowing for objects that don't implement it). So you can have an object that has a to_model
that points to an active model that's persisted, but have a form with a POST because the object passed in doesn't implement it.
So it feels more like a bugfix than a breaking change? Maybe I'm missing some use cases?
@@ -438,7 +438,7 @@ def form_for(record, options = {}, &block) | |||
model = nil | |||
object_name = record | |||
else | |||
model = convert_to_model(record) | |||
model = record |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't really need model
anymore, we could pass record
to form_with
directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was hoping to avoid mixing too many refactoring changes with changes to the behavior. Inlining apply_form_for_options!
feels reasonable, but might even be better suited as a follow-up PR.
While the parallel declarations might be confusing, it's a pattern that pre-dates this change so I felt like it was worth sticking with.
If it's decided that this isn't a breaking change, and that it's a worthwhile bugfix, I'd feel more comfortable broadening the scope to include some variable clean up. What do you think?
677b5fd
to
24321f0
Compare
cc @gmcgibbon @byroot I think this is reasonable, I have a hard time finding an incompatibility that this would cause. If you implement Also weird is that since we will call |
I like the general idea, but I'm a bit confused as I don't see any call to Also such new feature needs a CHANGELOG. |
24321f0
to
95fd64e
Compare
@byroot In order to shrink the diff back to its original size, I've reverted the refactor commit. With those incidental changes reverted, the focus of the diff involves the timing of calls to
The original change this is a follow-up to included a
This PR was split in response to #44328 (comment), though I'm not quite sure how to most clearly characterize the (breaking) change into a new CHANGELOG entry. |
@seanpdoyle ah, I see. Can you rework the PR title and description then, cause it's very hard to review in its current form. |
It's the |
form_with
: Attempt to call to_model on model:
convert_to_model
call from form_for
into form_with
@byroot I've renamed the PR title and tried to distill the change into the PR description. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because this changes the behaviour of form_with
, I think we should still add a changelog. Besides that this LGTM 👍
Ensure models passed to `form_with` attempt to call `to_model`. Now that `form_for` is implemented in terms of `form_with`, this commit also removes the `convert_to_model` call from the `form_for` implementation. To exercise this behavior, change existing `form_with` test coverage. Prior to this change, a call to `form_with` made with a `model:` argument that responds to `to_model` would not incorporate the instance's persistence state into the form's HTTP verb. After this change, the persistence state inferred from the `model:` argument's `to_model` call is incorporated into the `<form>` element's `[method]` attribute. This is a separate follow-up change proposed in [rails#44328][]. The original change to restore old behavior _deliberately_ excluded applying the same logic to `form_with`, since it would be a breaking change from how `form_with` behaved previously. This commit proposed making that breaking change. [rails#44328]: rails#44328 (comment)
95fd64e
to
980de46
Compare
@gmcgibbon I've added a CHANGELOG entry. |
Upgrading to Rails 7.1 causes the RejectionReasons model to be passed as the `object_name` when rendering errors. This model doesn't hold any errors when it's passed to the form builder. This is because `form_with` now calls `#to_model` on the object passed to the form whereas it didn't in Rails 7. It's better that we don't depend on the internals of Rails for this feature. **Rails 7..7.1 fixes for `#to_model`** rails/rails#43421 rails/rails#44326 rails/rails#44468
Upgrading to Rails 7.1 causes the RejectionReasons model to be passed as the `object_name` when rendering errors. This model doesn't hold any errors when it's passed to the form builder. This is because `form_with` now calls `#to_model` on the object passed to the form whereas it didn't in Rails 7. It's better that we don't depend on the internals of Rails for this feature. **Rails 7..7.1 fixes for `#to_model`** rails/rails#43421 rails/rails#44326 rails/rails#44468
Summary
Ensure models passed to
form_with
attempt to callto_model
.Now that
form_for
is implemented in terms ofform_with
, this commitalso removes the
convert_to_model
call from theform_for
implementation.To exercise this behavior, change existing
form_with
test coverage.Prior to this change, a call to
form_with
made with amodel:
argumentthat responds to
to_model
would not incorporate the instance's persistencestate into the form's HTTP verb. After this change, the persistence state
inferred from the
model:
argument'sto_model
call is incorporated intothe
<form>
element's[method]
attribute.This is a separate follow-up change proposed in rails/rails#44328.
The original change to restore old behavior deliberately excluded
applying the same logic to
form_with
, since it would be a breakingchange from how
form_with
behaved previously.This commit proposed making that breaking change.