Google is explicit that a multi-word URL of the format /blue-socks is superior to /blue_socks in the sense that only the former will be recognized as “blue socks”. (A better example is perhaps an important-for-SEO page like “/competitive-comparison” where the underscore version of the URL is very much inferior for SEO.)
Yet, unless I’m missing something - I hope! - it seems to me that Rails is just not at all accommodating of using SEO-friendlier (hyphenated) routes/paths/urls.
Given an example controller method for a static page about “blue socks” it appears to me that - even now in Rails 7 in this SEO-is-essential world - the hard-wired Rails-way is still def blue_socks ... which will always create underscored routes, paths, and urls (`blue_socks’) as opposed to the SEO friendly format “blue-socks”.
Certainly, one canmanually create SEO-friendly duplicate routes so that /blue-socks will indeed get to the correct page. But one still cannot (AFAIK) use any of the Rails niceties (path and url helpers) to insert the SEO friendly version of the route into any view or sitemap. E.g, in a view, using blue_socks_home_url will always return the underscored version of the url.
So, assuming a developer wants their app to include canonical urls, a sitemap, and cross-links between pages - all with hyphenated urls for optimal SEO - it seems to me that 100% of the routing-related auto-magic niceties of Rails get relegated to the waste bin and the developer must do 100% of url referencing manually. I hope I’m wrong! (I did try the gem canonical-rails gem hoping it might address hyphenated urls, but it seems designed only to handle the issue of inserting the - underscored - canonical url into a view. Handy, I suppose, yet the hyphenated-url issue remains.)
If you’ve taken the time to set up your routes to use SEO-friendly “slugs” (instead of numerical IDs or UUIDs) in your URLs, then you are the one making those strings, as far as I can tell. Take a look at the ActiveSupport parameterize string method for a really well considered way to turn a string containing underscores (as well as spaces, or punctuation, or URL-illegal characters) into something very-search-friendly.
If you’re talking about the intermediate segments in the URL, like the controller name, then those are configurable in the routes file, I believe, but I have not seen that done very much. If you could say a little more about the exact parts of the URL you want to change, maybe someone could point you toward a more specific solution.
Dynamic links (e.g., blog posts) are no problem since (as you say) we control them.
But assume a simple, mostly-static-page product website. 20 static pages defined in a home controller as: def contact_us, and def about_us, and def pricing, and def competitive_comparison, etc
So - at least out of the box, Rails has everything related to “competitive_comparison” underscored… if we insert a link to a page using the helper competitive_comparison_path it naturally inserts the link /competitive_comparison … and what we want (for SEO reasons) is all those multi-word static page urls to look like /competitive-comparison so that google “sees” the individual words (not just a long non-word).
Since (AFAIK) there is not any way to create a controller method named “competitive-comparison” it looks like with Rails it is “underscores all the way down” … method name… view file name… path… url…
So I’m hoping a reasonable goal is “simply” (well, as simply as possible) to be able to get Rails helpers to create SEO-friendlier (hyphenated) paths and urls for multi-word paths and urls in all internal links and canonical links and sitemap.xml links.
Maybe there’s a misconception between method names, route helpers and the actual URL which gets generated.
Rails doesn’t automatically generate URLs for you. It only respects whatever you type in the routes.rb file. Now, if you’re using the resource or resources methods then you’ll need to customise the route’s output. That’s the only method I know will automatically underscore the url. And actually, I don’t know it it’s possible to use a string instead of a symbol. I’m on my phone now so I can’t test this but maybe it just works: