Skip to content

Commit 876d2ff

Browse files
authored
Merge PR rails#43409
2 parents 27d24e9 + 37081bf commit 876d2ff

File tree

6 files changed

+241
-9
lines changed

6 files changed

+241
-9
lines changed

actionview/CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
* Introduce the `field_name` view helper, along with the
2+
`FormBuilder#field_name` counterpart:
3+
4+
```ruby
5+
form_for @post do |f|
6+
f.field_tag :tag, name: f.field_name(:tag, multiple: true)
7+
# => <input type="text" name="post[tag][]">
8+
end
9+
```
10+
11+
*Sean Doyle*
12+
113
* Execute the `ActionView::Base.field_error_proc` within the context of the
214
`ActionView::Base` instance:
315

actionview/lib/action_view/helpers/form_helper.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1769,6 +1769,28 @@ def field_id(method, *suffixes, index: @index)
17691769
@template.field_id(@object_name, method, *suffixes, index: index)
17701770
end
17711771

1772+
# Generate an HTML <tt>name</tt> attribute value for the given name and
1773+
# field combination
1774+
#
1775+
# Return the value generated by the <tt>FormBuilder</tt> for the given
1776+
# attribute name.
1777+
#
1778+
# <%= form_for @post do |f| %>
1779+
# <%= f.text_field :title, name: f.field_name(:title, :subtitle) %>
1780+
# <%# => <input type="text" name="post[title][subtitle]">
1781+
# <% end %>
1782+
#
1783+
# <%= form_for @post do |f| %>
1784+
# <%= f.field_tag :tag, name: f.field_name(:tag, multiple: true) %>
1785+
# <%# => <input type="text" name="post[tag][]">
1786+
# <% end %>
1787+
#
1788+
def field_name(method, *methods, multiple: false, index: @index)
1789+
object_name = @options.fetch(:as) { @object_name }
1790+
1791+
@template.field_name(object_name, method, *methods, index: index, multiple: multiple)
1792+
end
1793+
17721794
##
17731795
# :method: text_field
17741796
#

actionview/lib/action_view/helpers/form_tag_helper.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,32 @@ def field_id(object_name, method_name, *suffixes, index: nil)
117117
end
118118
end
119119

120+
# Generate an HTML <tt>name</tt> attribute value for the given name and
121+
# field combination
122+
#
123+
# Return the value generated by the <tt>FormBuilder</tt> for the given
124+
# attribute name.
125+
#
126+
# <%= text_field_tag :post, :title, name: field_name(:post, :title, :subtitle) %>
127+
# <%# => <input type="text" name="post[title][subtitle]">
128+
#
129+
# <%= text_field_tag :post, :tag, name: field_name(:post, :tag, multiple: true) %>
130+
# <%# => <input type="text" name="post[tag][]">
131+
#
132+
def field_name(object_name, method_name, *method_names, multiple: false, index: nil)
133+
names = method_names.map! { |name| "[#{name}]" }.join
134+
135+
# a little duplication to construct fewer strings
136+
case
137+
when object_name.empty?
138+
"#{method_name}#{names}#{multiple ? "[]" : ""}"
139+
when index
140+
"#{object_name}[#{index}][#{method_name}]#{names}#{multiple ? "[]" : ""}"
141+
else
142+
"#{object_name}[#{method_name}]#{names}#{multiple ? "[]" : ""}"
143+
end
144+
end
145+
120146
# Creates a dropdown selection box, or if the <tt>:multiple</tt> option is set to true, a multiple
121147
# choice selection box.
122148
#

actionview/lib/action_view/helpers/tags/base.rb

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,7 @@ def add_default_name_and_id(options)
105105
end
106106

107107
def tag_name(multiple = false, index = nil)
108-
# a little duplication to construct fewer strings
109-
case
110-
when @object_name.empty?
111-
"#{sanitized_method_name}#{multiple ? "[]" : ""}"
112-
when index
113-
"#{@object_name}[#{index}][#{sanitized_method_name}]#{multiple ? "[]" : ""}"
114-
else
115-
"#{@object_name}[#{sanitized_method_name}]#{multiple ? "[]" : ""}"
116-
end
108+
@template_object.field_name(@object_name, sanitized_method_name, multiple: multiple, index: index)
117109
end
118110

119111
def tag_id(index = nil)

actionview/test/template/form_helper_test.rb

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1677,6 +1677,126 @@ def test_form_for_field_id_with_index
16771677
assert_dom_equal expected, output_buffer
16781678
end
16791679

1680+
def test_form_for_field_name_with_blank_as
1681+
form_for(Post.new, as: "") do |form|
1682+
concat form.text_field(:title, name: form.field_name(:title))
1683+
end
1684+
1685+
expected = whole_form("/posts", "new_", "new_") do
1686+
%(<input id="title" name="title" type="text">)
1687+
end
1688+
1689+
assert_dom_equal expected, output_buffer
1690+
end
1691+
1692+
def test_form_for_field_name_with_blank_as_and_multiple
1693+
form_for(Post.new, as: "") do |form|
1694+
concat form.text_field(:title, name: form.field_name(:title, multiple: true))
1695+
end
1696+
1697+
expected = whole_form("/posts", "new_", "new_") do
1698+
%(<input id="title" name="title[]" type="text">)
1699+
end
1700+
1701+
assert_dom_equal expected, output_buffer
1702+
end
1703+
1704+
def test_form_for_field_name_without_method_names_or_multiple_or_index
1705+
form_for(Post.new) do |form|
1706+
concat form.text_field(:title, name: form.field_name(:title))
1707+
end
1708+
1709+
expected = whole_form("/posts", "new_post", "new_post") do
1710+
%(<input id="post_title" name="post[title]" type="text">)
1711+
end
1712+
1713+
assert_dom_equal expected, output_buffer
1714+
end
1715+
1716+
def test_form_for_field_name_without_method_names_and_multiple
1717+
form_for(Post.new) do |form|
1718+
concat form.text_field(:title, name: form.field_name(:title, multiple: true))
1719+
end
1720+
1721+
expected = whole_form("/posts", "new_post", "new_post") do
1722+
%(<input id="post_title" name="post[title][]" type="text">)
1723+
end
1724+
1725+
assert_dom_equal expected, output_buffer
1726+
end
1727+
1728+
def test_form_for_field_name_without_method_names_and_index
1729+
form_for(Post.new, index: 1) do |form|
1730+
concat form.text_field(:title, name: form.field_name(:title))
1731+
end
1732+
1733+
expected = whole_form("/posts", "new_post", "new_post") do
1734+
%(<input id="post_1_title" name="post[1][title]" type="text">)
1735+
end
1736+
1737+
assert_dom_equal expected, output_buffer
1738+
end
1739+
1740+
def test_form_for_field_name_without_method_names_and_index_and_multiple
1741+
form_for(Post.new, index: 1) do |form|
1742+
concat form.text_field(:title, name: form.field_name(:title, multiple: true))
1743+
end
1744+
1745+
expected = whole_form("/posts", "new_post", "new_post") do
1746+
%(<input id="post_1_title" name="post[1][title][]" type="text">)
1747+
end
1748+
1749+
assert_dom_equal expected, output_buffer
1750+
end
1751+
1752+
def test_form_for_field_name_with_method_names
1753+
form_for(Post.new) do |form|
1754+
concat form.text_field(:title, name: form.field_name(:title, :subtitle))
1755+
end
1756+
1757+
expected = whole_form("/posts", "new_post", "new_post") do
1758+
%(<input id="post_title" name="post[title][subtitle]" type="text">)
1759+
end
1760+
1761+
assert_dom_equal expected, output_buffer
1762+
end
1763+
1764+
def test_form_for_field_name_with_method_names_and_index
1765+
form_for(Post.new, index: 1) do |form|
1766+
concat form.text_field(:title, name: form.field_name(:title, :subtitle))
1767+
end
1768+
1769+
expected = whole_form("/posts", "new_post", "new_post") do
1770+
%(<input id="post_1_title" name="post[1][title][subtitle]" type="text">)
1771+
end
1772+
1773+
assert_dom_equal expected, output_buffer
1774+
end
1775+
1776+
def test_form_for_field_name_with_method_names_and_multiple
1777+
form_for(Post.new) do |form|
1778+
concat form.text_field(:title, name: form.field_name(:title, :subtitle, multiple: true))
1779+
end
1780+
1781+
expected = whole_form("/posts", "new_post", "new_post") do
1782+
%(<input id="post_title" name="post[title][subtitle][]" type="text">)
1783+
end
1784+
1785+
assert_dom_equal expected, output_buffer
1786+
end
1787+
1788+
def test_form_for_field_name_with_method_names_and_multiple_and_index
1789+
form_for(Post.new, index: 1) do |form|
1790+
concat form.text_field(:title, name: form.field_name(:title, :subtitle, multiple: true))
1791+
end
1792+
1793+
expected = whole_form("/posts", "new_post", "new_post") do
1794+
%(<input id="post_1_title" name="post[1][title][subtitle][]" type="text">)
1795+
end
1796+
1797+
assert_dom_equal expected, output_buffer
1798+
end
1799+
16801800
def test_form_for_with_collection_radio_buttons
16811801
post = Post.new
16821802
def post.active; false; end

actionview/test/template/form_tag_helper_test.rb

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,66 @@ def test_field_id_with_nested_object_name
225225
assert_equal "post_author_name", value
226226
end
227227

228+
def test_field_name_without_object_name
229+
value = field_name("", :title)
230+
231+
assert_equal "title", value
232+
end
233+
234+
def test_field_name_without_object_name_and_multiple
235+
value = field_name("", :title, multiple: true)
236+
237+
assert_equal "title[]", value
238+
end
239+
240+
def test_field_name_without_method_names_or_multiple_or_index
241+
value = field_name(:post, :title)
242+
243+
assert_equal "post[title]", value
244+
end
245+
246+
def test_field_name_without_method_names_and_multiple
247+
value = field_name(:post, :title, multiple: true)
248+
249+
assert_equal "post[title][]", value
250+
end
251+
252+
def test_field_name_without_method_names_and_index
253+
value = field_name(:post, :title, index: 1)
254+
255+
assert_equal "post[1][title]", value
256+
end
257+
258+
def test_field_name_without_method_names_and_index_and_multiple
259+
value = field_name(:post, :title, index: 1, multiple: true)
260+
261+
assert_equal "post[1][title][]", value
262+
end
263+
264+
def test_field_name_with_method_names
265+
value = field_name(:post, :title, :subtitle)
266+
267+
assert_equal "post[title][subtitle]", value
268+
end
269+
270+
def test_field_name_with_method_names_and_index
271+
value = field_name(:post, :title, :subtitle, index: 1)
272+
273+
assert_equal "post[1][title][subtitle]", value
274+
end
275+
276+
def test_field_name_with_method_names_and_multiple
277+
value = field_name(:post, :title, :subtitle, multiple: true)
278+
279+
assert_equal "post[title][subtitle][]", value
280+
end
281+
282+
def test_field_name_with_method_names_and_multiple_and_index
283+
value = field_name(:post, :title, :subtitle, index: 1, multiple: true)
284+
285+
assert_equal "post[1][title][subtitle][]", value
286+
end
287+
228288
def test_hidden_field_tag
229289
actual = hidden_field_tag "id", 3
230290
expected = %(<input id="id" name="id" type="hidden" value="3" autocomplete="off" />)

0 commit comments

Comments
 (0)