Skip to content

Commit 159ce69

Browse files
authored
Merge pull request rails#44328 from seanpdoyle/form-for-to-model
`form_for`: Attempt to call `to_model` on first argument
2 parents 9655240 + 9dc083f commit 159ce69

File tree

4 files changed

+45
-1
lines changed

4 files changed

+45
-1
lines changed

actionview/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
* Ensure models passed to `form_for` attempt to call `to_model`.
12

3+
*Sean Doyle*
24

35
Please check [7-0-stable](https://github.com/rails/rails/blob/7-0-stable/actionview/CHANGELOG.md) for previous changes.

actionview/lib/action_view/helpers/form_helper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ def form_for(record, options = {}, &block)
438438
model = nil
439439
object_name = record
440440
else
441-
model = record
441+
model = convert_to_model(record)
442442
object = _object_for_form_builder(record)
443443
raise ArgumentError, "First argument in form cannot contain nil or be empty" unless object
444444
object_name = options[:as] || model_name_from_record_or_class(object).param_key

actionview/test/template/form_helper/form_with_test.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ def @post.to_param; "123"; end
309309
@controller.singleton_class.include Routes.url_helpers
310310
end
311311

312+
RecordForm = Struct.new(:to_model, keyword_init: true)
312313
Routes = ActionDispatch::Routing::RouteSet.new
313314
Routes.draw do
314315
resources :posts do
@@ -381,6 +382,26 @@ def test_form_with
381382
assert_dom_equal expected, output_buffer
382383
end
383384

385+
def test_form_with_with_persisted_to_model
386+
post_form = RecordForm.new(to_model: @post)
387+
388+
form_with(model: post_form) { }
389+
390+
expected = whole_form("/posts/123", method: :post) { "" }
391+
392+
assert_dom_equal expected, output_buffer
393+
end
394+
395+
def test_form_with_with_new_record_to_model
396+
post_form = RecordForm.new(to_model: Post.new)
397+
398+
form_with(model: post_form) { }
399+
400+
expected = whole_form("/posts", method: :post) { "" }
401+
402+
assert_dom_equal expected, output_buffer
403+
end
404+
384405
def test_form_with_button_yields_translation
385406
form_with(model: @post) do |f|
386407
concat(f.button { |value| concat content_tag(:span, value) })

actionview/test/template/form_helper_test.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ def @post.to_param; "123"; end
143143
@controller.singleton_class.include Routes.url_helpers
144144
end
145145

146+
RecordForm = Struct.new(:to_model, keyword_init: true)
146147
Routes = ActionDispatch::Routing::RouteSet.new
147148
Routes.draw do
148149
resources :posts do
@@ -2076,6 +2077,26 @@ def post.tag_ids; [1]; end
20762077
assert_dom_equal expected, output_buffer
20772078
end
20782079

2080+
def test_form_for_with_persisted_to_model
2081+
post_form = RecordForm.new(to_model: @post)
2082+
2083+
form_for(post_form) { }
2084+
2085+
expected = whole_form("/posts/123", "edit_post_123", "edit_post", method: :patch) { "" }
2086+
2087+
assert_dom_equal expected, output_buffer
2088+
end
2089+
2090+
def test_form_for_with_new_record_to_model
2091+
post_form = RecordForm.new(to_model: Post.new)
2092+
2093+
form_for(post_form) { }
2094+
2095+
expected = whole_form("/posts", "new_post", "new_post", method: :post) { "" }
2096+
2097+
assert_dom_equal expected, output_buffer
2098+
end
2099+
20792100
def test_form_for_with_file_field_generate_multipart
20802101
form_for(@post, html: { id: "create-post" }) do |f|
20812102
concat f.file_field(:file)

0 commit comments

Comments
 (0)