This blog is part of our Rails 6.1 series.
From Rails 6.1 onwards, the default behavior of the Rails generator when encountering an impossible "camelCase" inflection would be to raise an error, rather than generating a name that will cause problems.
What are impossible "camelCase" inflections?
The Rails Inflector is part of the ActiveSupport module, and it comes shipped with patterns to transform Ruby strings. This library is responsible for pluralization and/or singularization of strings.
The Inflector tries its best to provide the desired result given a string. But sometimes, with certain words, it can't provide say the pluralized version out of the box.
Let's say for example the string is DSL. The desired plural form is DSLs. But the Inflector gets confused on what exactly is the desired plural form or more accurately what exactly is the underscore resource name and it used to generate inconsistent class names.
Before Rails 6.1
Let's try out the following example.
1bundle exec rails g scaffold DSL field
In the output we can see that the controller filename is ds_ls_controller.rb and the controller class name is:
1class DsLsController < ApplicationController
And the routes file is populated with:
You see the problem right?
The generated route :dsls expects a DslsController controller but the controller generated is DsLsController. This will lead to a routing error.
How Rails 6.1 solves this problem?
The Rails team decided that it would be better to terminate the generation process with an error rather than generating classes that are internally inconsistent.
Thus Rails now raises an error in the following two scenarios where the casing is impossible to be inflected:
The first case is when "camelCased" model name is passed to a generator. The second case is when the full round trip from pluralize to singularize does not match with the original singular value. Rails checks for the following condition.
1name.pluralize.underscore.singularize != name.underscore.singularize
We can try out the same example that we did in the previous section and it will provide the following output:
1Rails cannot recover the underscored form from its camelcase form 'DSL'. 2Please use an underscored name instead, either 'dsl' or 'ds_l'. 3Or set up custom inflection rules for this noun before running the generator in config/initializers/inflections.rb.
This allows the developers to either rephrase the resource name with an underscored name from the very beginning itself or follow the suggestion, that is to create a custom inflection.
Creating a custom inflection
ActiveSupport::Inflector provides us with the inflections method in order to create our own custom inflections. This method can even accept an optional locale, which comes in handy when we are writing inflection rules for languages other than :en, which is the default locale.
You can have a detailed look into the inflection methods over here.
Let's try to make the above example work and get the desired underscore name for the string DSL. We’re dealing with an irregular inflection. Thus we can make use of the irregular method, which takes two arguments: the singular and the plural form of the word as strings.
Let's just add the custom inflection into config/initializers/inflections.rb:
1# We provide the string in lowercase format 2ActiveSupport::Inflector.inflections(:en) do |inflect| 3 inflect.irregular 'dsl', 'dsls' 4end
Voila! That's it.
Now if we run rails g scaffold DSL, we will be able to get the correct file and class names.