December 15, 2020
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.
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.
Let's try out the following example.
bundle 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:
class DsLsController < ApplicationController
And the routes file is populated with:
resources :dsls
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.
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.
name.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:
Rails cannot recover the underscored form from its camelcase form 'DSL'.
Please use an underscored name instead, either 'dsl' or 'ds_l'.
Or 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.
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
:
# We provide the string in lowercase format
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.irregular 'dsl', 'dsls'
end
Voila! That's it.
Now if we run rails g scaffold DSL
,
we will be able to get the correct file and class names.
Check out the pull request and the issue for more details.
If this blog was helpful, check out our full blog archive.