Skip to content

Commit 4997cc7

Browse files
committed
Implement form_for by delegating to form_with
Improve the parity between `form_for` and `form_with` by implementing `form_for` in terms of `form_with`. Replaces `html_options` transformations with coercion of data into the shape it needs to be in order to delegate to `form_with`. In the same spirit, this commit also implements `fields_for` in terms of `fields`.
1 parent bcb6c35 commit 4997cc7

File tree

2 files changed

+30
-31
lines changed

2 files changed

+30
-31
lines changed

actionview/lib/action_view/helpers/form_helper.rb

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -432,52 +432,45 @@ module FormHelper
432432
# <% end %>
433433
def form_for(record, options = {}, &block)
434434
raise ArgumentError, "Missing block" unless block_given?
435-
html_options = options[:html] ||= {}
436435

437436
case record
438437
when String, Symbol
438+
model = nil
439439
object_name = record
440-
object = nil
441440
else
441+
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
445-
apply_form_for_options!(record, object, options)
445+
apply_form_for_options!(object, options)
446446
end
447447

448-
html_options[:data] = options.delete(:data) if options.has_key?(:data)
449-
html_options[:remote] = options.delete(:remote) if options.has_key?(:remote)
450-
html_options[:method] = options.delete(:method) if options.has_key?(:method)
451-
html_options[:enforce_utf8] = options.delete(:enforce_utf8) if options.has_key?(:enforce_utf8)
452-
html_options[:authenticity_token] = options.delete(:authenticity_token)
448+
remote = options.delete(:remote)
453449

454-
builder = instantiate_builder(object_name, object, options)
455-
output = capture(builder, &block)
456-
html_options[:multipart] ||= builder.multipart?
450+
if remote && !embed_authenticity_token_in_remote_forms && options[:authenticity_token].blank?
451+
options[:authenticity_token] = false
452+
end
453+
454+
options[:model] = model
455+
options[:scope] = object_name
456+
options[:local] = !remote
457+
options[:skip_default_ids] = false
458+
options[:allow_method_names_outside_object] = options.fetch(:allow_method_names_outside_object, false)
457459

458-
html_options = html_options_for_form(options.fetch(:url, {}), html_options)
459-
form_tag_with_body(html_options, output)
460+
form_with(**options, &block)
460461
end
461462

462-
def apply_form_for_options!(record, object, options) # :nodoc:
463+
def apply_form_for_options!(object, options) # :nodoc:
463464
object = convert_to_model(object)
464465

465466
as = options[:as]
466467
namespace = options[:namespace]
467-
action, method = object.respond_to?(:persisted?) && object.persisted? ? [:edit, :patch] : [:new, :post]
468+
action = object.respond_to?(:persisted?) && object.persisted? ? :edit : :new
469+
options[:html] ||= {}
468470
options[:html].reverse_merge!(
469471
class: as ? "#{action}_#{as}" : dom_class(object, action),
470472
id: (as ? [namespace, action, as] : [namespace, dom_id(object, action)]).compact.join("_").presence,
471-
method: method
472473
)
473-
474-
if options[:url] != false
475-
options[:url] ||= if options.key?(:format)
476-
polymorphic_path(record, format: options.delete(:format))
477-
else
478-
polymorphic_path(record, {})
479-
end
480-
end
481474
end
482475
private :apply_form_for_options!
483476

@@ -1023,8 +1016,9 @@ def form_with(model: nil, scope: nil, url: nil, format: nil, **options, &block)
10231016
# hidden field is not needed and you can pass <tt>include_id: false</tt>
10241017
# to prevent fields_for from rendering it automatically.
10251018
def fields_for(record_name, record_object = nil, options = {}, &block)
1026-
builder = instantiate_builder(record_name, record_object, options)
1027-
capture(builder, &block)
1019+
options = { model: record_object, allow_method_names_outside_object: false, skip_default_ids: false }.merge!(options)
1020+
1021+
fields(record_name, **options, &block)
10281022
end
10291023

10301024
# Scopes input fields with either an explicit scope or model.
@@ -1073,8 +1067,7 @@ def fields_for(record_name, record_object = nil, options = {}, &block)
10731067
# to work with an object as a base, like
10741068
# FormOptionsHelper#collection_select and DateHelper#datetime_select.
10751069
def fields(scope = nil, model: nil, **options, &block)
1076-
options[:allow_method_names_outside_object] = true
1077-
options[:skip_default_ids] = !form_with_generates_ids
1070+
options = { allow_method_names_outside_object: true, skip_default_ids: !form_with_generates_ids }.merge!(options)
10781071

10791072
if model
10801073
model = _object_for_form_builder(model)
@@ -1575,9 +1568,15 @@ def _object_for_form_builder(object) # :nodoc:
15751568
def html_options_for_form_with(url_for_options = nil, model = nil, html: {}, local: !form_with_generates_remote_forms,
15761569
skip_enforcing_utf8: nil, **options)
15771570
html_options = options.slice(:id, :class, :multipart, :method, :data, :authenticity_token).merge!(html)
1578-
html_options[:remote] = !local
1571+
html_options[:remote] = html.delete(:remote) || !local
15791572
html_options[:method] ||= :patch if model.respond_to?(:persisted?) && model.persisted?
1580-
html_options[:enforce_utf8] = !skip_enforcing_utf8 unless skip_enforcing_utf8.nil?
1573+
if skip_enforcing_utf8.nil?
1574+
if options.key?(:enforce_utf8)
1575+
html_options[:enforce_utf8] = options[:enforce_utf8]
1576+
end
1577+
else
1578+
html_options[:enforce_utf8] = !skip_enforcing_utf8
1579+
end
15811580
html_options_for_form(url_for_options.nil? ? {} : url_for_options, html_options)
15821581
end
15831582

actionview/lib/action_view/helpers/form_tag_helper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ def html_options_for_form(url_for_options, options)
914914
html_options["data-remote"] = true if html_options.delete("remote")
915915

916916
if html_options["data-remote"] &&
917-
!embed_authenticity_token_in_remote_forms &&
917+
embed_authenticity_token_in_remote_forms == false &&
918918
html_options["authenticity_token"].blank?
919919
# The authenticity token is taken from the meta tag in this case
920920
html_options["authenticity_token"] = false

0 commit comments

Comments
 (0)