Skip to content

Commit 1e9629e

Browse files
committed
Allow url_for to infer the name of the link from Model#to_s
1 parent dfef447 commit 1e9629e

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

actionview/CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,26 @@
1+
* Allow `link_to` helper to infer link name from `Model#to_s` when it
2+
is used with a single argument:
3+
4+
link_to @profile
5+
#=> <a href="/profiles/1">Eileen</a>
6+
7+
This assumes the model class implements a `to_s` method like this:
8+
9+
class Profile < ApplicationRecord
10+
# ...
11+
def to_s
12+
name
13+
end
14+
end
15+
16+
Previously you had to supply a second argument even if the `Profile`
17+
model implemented a `#to_s` method that called the `name` method.
18+
19+
link_to @profile, @profile.name
20+
#=> <a href="/profiles/1">Eileen</a>
21+
22+
*Olivier Lacan*
23+
124
* Add `weekday_options_for_select` and `weekday_select` helper methods. Also adds `weekday_select` to `FormBuilder`.
225

326
*Drew Bragg*, *Dana Kashubeck*, *Kasper Timm Hansen*

actionview/lib/action_view/helpers/url_helper.rb

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ def _filtered_referrer # :nodoc:
8585
# # name
8686
# end
8787
#
88+
# link_to(active_record_model)
89+
#
8890
# ==== Options
8991
# * <tt>:data</tt> - This option can be used to add custom data attributes.
9092
# * <tt>method: symbol of HTTP verb</tt> - This modifier will dynamically
@@ -146,6 +148,12 @@ def _filtered_referrer # :nodoc:
146148
# link_to nil, "http://example.com"
147149
# # => <a href="http://www.example.com">http://www.example.com</a>
148150
#
151+
# More concise yet, when +name+ is an ActiveRecord model that defines a
152+
# +to_s+ method returning a default value or a model instance attribute
153+
#
154+
# link_to @profile
155+
# # => <a href="http://www.example.com/profiles/1">Eileen</a>
156+
#
149157
# You can use a block as well if your link target is hard to fit into the name parameter. ERB example:
150158
#
151159
# <%= link_to(@profile) do %>
@@ -201,7 +209,7 @@ def link_to(name = nil, options = nil, html_options = nil, &block)
201209

202210
html_options = convert_options_to_data_attributes(options, html_options)
203211

204-
url = url_for(options)
212+
url = url_target(name, options)
205213
html_options["href"] ||= url
206214

207215
content_tag("a", name || url, html_options, &block)
@@ -716,6 +724,14 @@ def convert_options_to_data_attributes(options, html_options)
716724
end
717725
end
718726

727+
def url_target(name, options)
728+
if name.respond_to?(:model_name) && options.empty?
729+
url_for(name)
730+
else
731+
url_for(options)
732+
end
733+
end
734+
719735
def link_to_remote_options?(options)
720736
if options.is_a?(Hash)
721737
options.delete("remote") || options.delete(:remote)

actionview/test/template/url_helper_test.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class UrlHelperTest < ActiveSupport::TestCase
3535
get "/other" => "foo#other"
3636
get "/article/:id" => "foo#article", :as => :article
3737
get "/category/:category" => "foo#category"
38+
resources :workshops
3839

3940
scope :engine do
4041
get "/" => "foo#bar"
@@ -511,6 +512,12 @@ def test_link_tag_does_not_escape_html_safe_content
511512
link_to(raw("Malicious <script>content</script>"), "/")
512513
end
513514

515+
def test_link_tag_using_active_record_model
516+
@workshop = Workshop.new(1.to_s)
517+
link = link_to(@workshop)
518+
assert_dom_equal %{<a href="/workshops/1">1</a>}, link
519+
end
520+
514521
def test_link_to_unless
515522
assert_equal "Showing", link_to_unless(true, "Showing", url_hash)
516523

0 commit comments

Comments
 (0)