1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge pull request #33547 from Ana06/patch-1

Use public_send in value_for_collection
This commit is contained in:
Matthew Draper 2018-08-22 23:39:07 +09:30
commit 047a893da7
3 changed files with 34 additions and 3 deletions

View file

@ -1,3 +1,13 @@
* Deprecate calling private model methods from view helpers.
For example, in methods like `options_from_collection_for_select`
and `collection_select` it is possible to call private methods from
the objects used.
Fixes #33546.
*Ana María Martínez Gómez*
* Fix issue with `button_to`'s `to_form_params`
`button_to` was throwing exception when invoked with `params` hash that

View file

@ -794,7 +794,7 @@ module ActionView
def extract_values_from_collection(collection, value_method, selected)
if selected.is_a?(Proc)
collection.map do |element|
element.send(value_method) if selected.call(element)
public_or_deprecated_send(element, value_method) if selected.call(element)
end.compact
else
selected
@ -802,7 +802,15 @@ module ActionView
end
def value_for_collection(item, value)
value.respond_to?(:call) ? value.call(item) : item.send(value)
value.respond_to?(:call) ? value.call(item) : public_or_deprecated_send(item, value)
end
def public_or_deprecated_send(item, value)
item.public_send(value)
rescue NoMethodError
raise unless item.respond_to?(value, true) && !item.respond_to?(value)
ActiveSupport::Deprecation.warn "Using private methods from view helpers is deprecated (calling private #{item.class}##{value})"
item.send(value)
end
def prompt_text(prompt)

View file

@ -21,7 +21,12 @@ class FormOptionsHelperTest < ActionView::TestCase
tests ActionView::Helpers::FormOptionsHelper
silence_warnings do
Post = Struct.new("Post", :title, :author_name, :body, :secret, :written_on, :category, :origin, :allow_comments)
Post = Struct.new("Post", :title, :author_name, :body, :written_on, :category, :origin, :allow_comments) do
private
def secret
"This is super secret: #{author_name} is not the real author of #{title}"
end
end
Continent = Struct.new("Continent", :continent_name, :countries)
Country = Struct.new("Country", :country_id, :country_name)
Firm = Struct.new("Firm", :time_zone)
@ -68,6 +73,14 @@ class FormOptionsHelperTest < ActionView::TestCase
)
end
def test_collection_options_with_private_value_method
assert_deprecated("Using private methods from view helpers is deprecated (calling private Struct::Post#secret)") { options_from_collection_for_select(dummy_posts, "secret", "title") }
end
def test_collection_options_with_private_text_method
assert_deprecated("Using private methods from view helpers is deprecated (calling private Struct::Post#secret)") { options_from_collection_for_select(dummy_posts, "author_name", "secret") }
end
def test_collection_options_with_preselected_value
assert_dom_equal(
"<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option value=\"Babe\" selected=\"selected\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option>",