Allow url_for to infer the name of the link from Model#to_s

This commit is contained in:
Olivier Lacan 2021-05-15 20:16:07 -04:00
parent dfef44716a
commit 1e9629e8a9
3 changed files with 47 additions and 1 deletions

View File

@ -1,3 +1,26 @@
* Allow `link_to` helper to infer link name from `Model#to_s` when it
is used with a single argument:
link_to @profile
#=> <a href="/profiles/1">Eileen</a>
This assumes the model class implements a `to_s` method like this:
class Profile < ApplicationRecord
# ...
def to_s
name
end
end
Previously you had to supply a second argument even if the `Profile`
model implemented a `#to_s` method that called the `name` method.
link_to @profile, @profile.name
#=> <a href="/profiles/1">Eileen</a>
*Olivier Lacan*
* Add `weekday_options_for_select` and `weekday_select` helper methods. Also adds `weekday_select` to `FormBuilder`.
*Drew Bragg*, *Dana Kashubeck*, *Kasper Timm Hansen*

View File

@ -85,6 +85,8 @@ module ActionView
# # name
# end
#
# link_to(active_record_model)
#
# ==== Options
# * <tt>:data</tt> - This option can be used to add custom data attributes.
# * <tt>method: symbol of HTTP verb</tt> - This modifier will dynamically
@ -146,6 +148,12 @@ module ActionView
# link_to nil, "http://example.com"
# # => <a href="http://www.example.com">http://www.example.com</a>
#
# More concise yet, when +name+ is an ActiveRecord model that defines a
# +to_s+ method returning a default value or a model instance attribute
#
# link_to @profile
# # => <a href="http://www.example.com/profiles/1">Eileen</a>
#
# You can use a block as well if your link target is hard to fit into the name parameter. ERB example:
#
# <%= link_to(@profile) do %>
@ -201,7 +209,7 @@ module ActionView
html_options = convert_options_to_data_attributes(options, html_options)
url = url_for(options)
url = url_target(name, options)
html_options["href"] ||= url
content_tag("a", name || url, html_options, &block)
@ -716,6 +724,14 @@ module ActionView
end
end
def url_target(name, options)
if name.respond_to?(:model_name) && options.empty?
url_for(name)
else
url_for(options)
end
end
def link_to_remote_options?(options)
if options.is_a?(Hash)
options.delete("remote") || options.delete(:remote)

View File

@ -35,6 +35,7 @@ class UrlHelperTest < ActiveSupport::TestCase
get "/other" => "foo#other"
get "/article/:id" => "foo#article", :as => :article
get "/category/:category" => "foo#category"
resources :workshops
scope :engine do
get "/" => "foo#bar"
@ -511,6 +512,12 @@ class UrlHelperTest < ActiveSupport::TestCase
link_to(raw("Malicious <script>content</script>"), "/")
end
def test_link_tag_using_active_record_model
@workshop = Workshop.new(1.to_s)
link = link_to(@workshop)
assert_dom_equal %{<a href="/workshops/1">1</a>}, link
end
def test_link_to_unless
assert_equal "Showing", link_to_unless(true, "Showing", url_hash)