[Feature] Fix long index name error automatically

Hello, I am a contractor currently working with Bullet Train by Andrew Culver.

Few months ago, we had created a script which would run rails db:migrate and if there is an index length error we update the migration file and add index options to the referenced column with the index_name that is less than the maximum allowed length.

What we are currently doing with the script :point_down:

  • You run rails db:migrate and get an error of long index length
  • You run bin/fix-long-index-name to fix the long index length error
  • Script will do the following:
    • Capture stderr and check if it is long index name error
    • Trim current index name generated automatically by Rails which is less than 64 characters
    • Update the migration file with the index: { name: "trimmed_index_name" } option
    • You can run rails db:migrate without any issue now

What I want to implement in Rails by creating a new PR :point_down:

  • Method “index_name(table_name, options)” located at “activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb” is responsible for generating index name automatically.
  • In this method, if user hasn’t provided options[:name] or in general term; not provided index: { name: "some_name" } in the migration file, we will call a method which can validate and trim the current index_name which is generated automatically.
  • We will call “validate_and_trim_index_length” inside the condition block if options[:column]
  • I want to introduce two methods to fix this error automatically (with the consent of user): “validate_and_trim_index_length” and “trim_index_name”
  • validate_and_trim_index_length will do the following:
    • Check if the current index name is longer than the allowed length i.e. 64 chars
    • Print the error and notify the user that index name is longer if check returns positive result
    • Ask user if they want to trim the index name and make it less than 64 chars automatically
    • If the answer is not “y”, return current index name
    • If the answer is “y”, call the method “trim_index_name” which will be responsible for trimming the current index name to make it less than 64 chars
  • “trim_index_name” will do the following:
    • Separate two table names (they are joined by “on”)
    • Leaving the word “index_” in the beginning, this method will start removing the level of namespacing from the beginning of first table and second table interchangeably until the index name is smaller than 64 chars

Example :point_down:

Let’s say we have an index name index_integrations_some_provider_installations_on_oauth_some_provider_account_id which has 80 chars and will be trimmed as the following:

  1. index_some_provider_installations_on_oauth_some_provider_account_id → 67 chars
  2. index_some_provider_installations_on_some_provider_account_id → 61 chars

I was going to create a PR directly but when reading contribution guideline, it was suggested to get enough support first so here we are :smiley:


@rafaelfranca I want to submit a PR for this, is it possible for you take a look over the description when you have time?

Implementation: Fix long index names automatically by trimming it as per user consent by coolprobn · Pull Request #1 · coolprobn/rails · GitHub


@coolprobn you should make the PR to rails/rails, here: Pull requests · rails/rails · GitHub, otherwise it won’t show up in the PR list to get reviewed.

Contributing to Ruby on Rails — Ruby on Rails Guides steps through exactly how to do this.

I had a quick look at your PR, and I’m not sure it would work since it would require the user to be able to interact with stdin, which isn’t always a guarantee when migrations are running. For example it probably wouldn’t work in a production environment.

I think a setting that automatically trims names longer than N characters (rather than raising) could be cool.

Thanks @ghiculescu for reviewing it!

You are 100% correct and I didn’t realize it. I will update the code as required and also keep in mind about what you have proposed.

Regarding the PR, I didn’t want to pollute Rails repo without first verifying the fix, I wanted to fix it as required before submitting an official PR.