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

fix to_param to maximize content

The documentation states that parameter values longer than 20 characters
will be truncated by words, but the example shows that a parameter based
on "David Heinemeier Hansson" (with id: 125) becomes "125-david" when
"David Heinemeier".length == 16 so why so short?

The answer lies in the use of the #truncate option omission: nil which
seems to have been intended to mean "nothing", but which actually causes
the default string "..." to be used. This causes #truncate to cleave
words until the "..." can be added and still remain within the requested
size of 20 characters.

The better option is omission: '' (which is probably what was originally
intended).

Furthermore, since the use of #parameterize will remove non-alphanumeric
characters, we can maximize the useful content of the output by calling
parameterize first and then giving truncate a separator: /-/ rather than
a space.
This commit is contained in:
Rob Biedenharn 2016-02-11 14:22:09 -05:00
parent c62ac07be8
commit 3b49d79223
3 changed files with 41 additions and 4 deletions

View file

@ -1,3 +1,14 @@
* Fix the generated `#to_param` method to use `omission:''` so that
the resulting output is actually up to 20 characters, not
effectively 17 to leave room for the default "...".
Also call `#parameterize` before `#truncate` and make the
`separator: /-/` to maximize the information included in the
output.
Fixes #23635
*Rob Biedenharn*
* Ensure concurrent invocations of the connection reaper cannot allocate the
same connection to two threads.

View file

@ -86,7 +86,7 @@ module ActiveRecord
#
# user = User.find_by(name: 'David Heinemeier Hansson')
# user.id # => 125
# user_path(user) # => "/users/125-david"
# user_path(user) # => "/users/125-david-heinemeier"
#
# Because the generated param begins with the record's +id+, it is
# suitable for passing to +find+. In a controller, for example:
@ -100,7 +100,7 @@ module ActiveRecord
define_method :to_param do
if (default = super()) &&
(result = send(method_name).to_s).present? &&
(param = result.squish.truncate(20, separator: /\s/, omission: nil).parameterize).present?
(param = result.squish.parameterize.truncate(20, separator: /-/, omission: '')).present?
"#{default}-#{param}"
else
default

View file

@ -29,10 +29,30 @@ class IntegrationTest < ActiveRecord::TestCase
assert_equal '4-flamboyant-software', firm.to_param
end
def test_to_param_class_method_truncates_words_properly
firm = Firm.find(4)
firm.name << ', Inc.'
assert_equal '4-flamboyant-software', firm.to_param
end
def test_to_param_class_method_truncates_after_parameterize
firm = Firm.find(4)
firm.name = "Huey, Dewey, & Louie LLC"
# 123456789T123456789v
assert_equal '4-huey-dewey-louie-llc', firm.to_param
end
def test_to_param_class_method_truncates_after_parameterize_with_hyphens
firm = Firm.find(4)
firm.name = "Door-to-Door Wash-n-Fold Service"
# 123456789T123456789v
assert_equal '4-door-to-door-wash-n', firm.to_param
end
def test_to_param_class_method_truncates
firm = Firm.find(4)
firm.name = 'a ' * 100
assert_equal '4-a-a-a-a-a-a-a-a-a', firm.to_param
assert_equal '4-a-a-a-a-a-a-a-a-a-a', firm.to_param
end
def test_to_param_class_method_truncates_edge_case
@ -41,10 +61,16 @@ class IntegrationTest < ActiveRecord::TestCase
assert_equal '4-david', firm.to_param
end
def test_to_param_class_method_truncates_case_shown_in_doc
firm = Firm.find(4)
firm.name = 'David Heinemeier Hansson'
assert_equal '4-david-heinemeier', firm.to_param
end
def test_to_param_class_method_squishes
firm = Firm.find(4)
firm.name = "ab \n" * 100
assert_equal '4-ab-ab-ab-ab-ab-ab', firm.to_param
assert_equal '4-ab-ab-ab-ab-ab-ab-ab', firm.to_param
end
def test_to_param_class_method_multibyte_character