From f72294fdc0ae7c9284aa4adf889d3bd684b67e44 Mon Sep 17 00:00:00 2001 From: Petrik Date: Mon, 13 Jul 2020 21:25:03 +0200 Subject: [PATCH] Raise if camelcase inflection impossible in generator When passing a camelcased model name to a generator sometimes it's impossible to inflect the casing. For example "BFF" will generate a route for the controller BffsController, but the controller generated is BfFsController. The casing is impossible to inflect if both: - a camelcased model name is passed to a generator - `name.pluralize.underscore.singularize != name.underscore.singularize` If this happens we raise an error. The error message explains the user can either us an underscored name or add an inflection instead. --- .../lib/rails/generators/model_helpers.rb | 28 +++++++++++++++++-- .../test/generators/model_generator_test.rb | 10 +++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/railties/lib/rails/generators/model_helpers.rb b/railties/lib/rails/generators/model_helpers.rb index 3676432d5c..b59749dd06 100644 --- a/railties/lib/rails/generators/model_helpers.rb +++ b/railties/lib/rails/generators/model_helpers.rb @@ -11,6 +11,11 @@ module Rails [WARNING] Rails cannot recover singular form from its plural form '%s'. Please setup custom inflection rules for this noun before running the generator in config/initializers/inflections.rb. WARNING + INFLECTION_IMPOSSIBLE_ERROR_MESSAGE = <<~ERROR + Rails cannot recover the underscored form from its camelcase form '%s'. + Please use an underscored name instead, either '%s' or '%s'. + Or setup custom inflection rules for this noun before running the generator in config/initializers/inflections.rb. + ERROR mattr_accessor :skip_warn def self.included(base) #:nodoc: @@ -19,7 +24,7 @@ module Rails def initialize(args, *_options) super - if name == name.pluralize && name.singularize != name.pluralize && !options[:force_plural] + if plural_model_name?(name) && !options[:force_plural] singular = name.singularize unless ModelHelpers.skip_warn say PLURAL_MODEL_NAME_WARN_MESSAGE % [name, singular] @@ -27,11 +32,30 @@ module Rails name.replace singular assign_names!(name) end - if name.singularize != name.pluralize.singularize && ! ModelHelpers.skip_warn + if inflection_impossible?(name) + option1 = name.singularize.underscore + option2 = name.pluralize.underscore.singularize + raise Error, INFLECTION_IMPOSSIBLE_ERROR_MESSAGE % [name, option1, option2] + end + if irregular_model_name?(name) && ! ModelHelpers.skip_warn say IRREGULAR_MODEL_NAME_WARN_MESSAGE % [name.pluralize] end ModelHelpers.skip_warn = true end + + private + def plural_model_name?(name) + name == name.pluralize && name.singularize != name.pluralize + end + + def irregular_model_name?(name) + name.singularize != name.pluralize.singularize + end + + def inflection_impossible?(name) + name != name.underscore && + name.singularize.underscore != name.pluralize.underscore.singularize + end end end end diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb index d6abaf7a6f..9cf7ef3220 100644 --- a/railties/test/generators/model_generator_test.rb +++ b/railties/test/generators/model_generator_test.rb @@ -68,6 +68,16 @@ class ModelGeneratorTest < Rails::Generators::TestCase assert_no_match("[WARNING] Rails cannot recover singular form from its plural form", regular_content) end + def test_impossible_inflection_rules_raises_an_error + content = capture(:stderr) { run_generator ["BFF"] } + message = <<~MESSAGE + Rails cannot recover the underscored form from its camelcase form 'BFF'. + Please use an underscored name instead, either 'bff' or 'bf_f'. + Or setup custom inflection rules for this noun before running the generator in config/initializers/inflections.rb. + MESSAGE + assert_match message, content + end + def test_model_with_underscored_parent_option run_generator ["account", "--parent", "admin/account"] assert_file "app/models/account.rb", /class Account < Admin::Account/