Seemingly buggy behavior of AR's #to_param

tl;dr Noticing that the URL for a model instance was surprisingly short, I discovered a mismatch between the doc and the implementation for AR’s to_param method.

Given the history of the #to_param method and various existing (closed) pull requests, I wasn’t sure if this would be considered an “Issue”/bug or a Feature request.

If you want to just jump right into the commit (which I’d like to turn into a pull request unless there are particular objections), here you go!

Otherwise, settle in for a story. Got yourself a tasty beverage? Comfortable? OK, here we go!

Once upon a time, I added a:

to_param :name

to a model that still had anemic little URLs.

One particular record had a name of “process background jobs” and its parameter was becoming “4-process”.

The docs for #to_param said that returned string would be truncated by words if longer than 20 characters.



“process background jobs”

Well, it sure seems like truncation was reasonable, but why not to “4-process-background”?

Turns out the option passed to the internal call to #truncate was omission: nil which was probably intended to not use any string when there was some truncation, but actually caused the default value of “…” to be used.

That means the word-by-word truncation plus the “…” needs to fit within the requested 20 characters and “process background…” is 21 so “background” gets lopped off, too, and “process…” is now safely under the limit.

Interestingly, had the name been just “process background”, it would have generated “4-process-background” in the first place as no truncation would be needed.

The correct way to make this happen is omission:‘’

Furthermore, the subsequent call to #parameterize eliminates non-alphanumeric characters before replacing them with ‘-’ and squeezing them. Therefore, calling .parameterize.truncate(20, separator: /-/, omission: ‘’) results in the most information from the indicated attribute.


Rob Biedenharn