Namely, when two people make changes to the same Rails codebase it can create a situation where they are forever locked into a contest of flip-flopping the order of columns/foreign-keys, etc in the db/schema.rb file each time they make changes.
The fix-db-schema-conflicts gem “fixes” this by prepending some code to the Rails schema generation that sorts everything before spitting it out to schema.rb.
Additionally it uses Rubocop to autoformat the generated file to use uniform spacing and column alignment.
Over the years I’ve maintained this gem the vast majority of issues surrounding it have come from Rubocop compatibility with Rails. The Rubocop autocorrect is really something that could be applied separately by any team and was only added to my gem as a convenience, which has turned into a huge mess in terms of gem maintenance. The real value of my gem comes from the ordering of the database schema.
I propose making a small change to Rails that integrates my gem’s schema sorting logic into Rails by default, with a configuration option to preserve the ordering if a specific application relies on column sort order for some reason.
This change would not affect structure.sql in any way.
In my mind this is a common source of frustration for every single Rails project that has more than contributor, and it is a simple, low-risk change (can be reverted with a configuration).
I would be very glad to do the work if it was desired.
What does the community think, before I spend time on a PR for this?
I’d rather see a public API that we could hook into safely. While the sorting sounds helpful, I’ve needed other behavior changes in the ruby schema dumper too.
For my usecase, I have a large monolith with over 100 team members. The churn and merge conflicts are constant and painful.
The schema file is over 13k lines with over 600 tables. I’ve been playing with some monkey patching to generate ruby schema dumps into multiple files in a subdir, one table per file.
It works, but I don’t look forward to future breaking changes.
I use postgresql, and I’ve hit this a couple of times. I think it happens when I’m working locally on migrations that I end up reverting.
The public API suggestion feels separate from this. Adding your custom schema dumper may make sense, but the default schema dumper should be robust.
The column alignment problem Jake mentions was solved already in 5.1.0:
https://github.com/rails/rails/pull/25675
Sorting columns follows the same spirit of minimizing conflicts / surprises in the database schema file.
In my experience, this ended up happening in most projects. If it’s a PostgreSQL database, it gets even worse since there is no easy way to change column order, short of re-creating the table (and by extension, the database, due to foreign keys).
Even running db:migrate vs. db:schema:load can yield different ordering. Sometimes these kinds of changes sneak into the codebase within a busy migration and become everyone’s problem.
This is something I’m struggling with as well on a weekly basis, since the databases on my work computer and home computer have ended up with different orders for a few tables. Every time I run migrations pushed from the other computer, there’s an unwanted change in schema.rb, and I have to manually git restore the schema file to prevent adding the changed order to my next commit. Not a huge issue, but definitely annoying, and fixing the column order manually in PostgreSQL feels a bit overkill (and quite frankly something that shouldn’t be necessary just to prevent unnecessary changes and possible merge conflicts - especially if multiple team members have to do it). I think this would definitely be a welcome change to Rails and I’d be happy to help with the implementation if needed
I’m also annoyed by created_at and updated_at not staying at the bottom of the column list after adding new columns to an existing table In auto-generated migrations they’re always at the bottom, so there definitely seems to be a consensus that they should be the last columns, but in a real-world situation, it’s not always possible to know all the columns you’re going to need for a table beforehand. Tables, foreign keys, and even enums are already sorted, so why wouldn’t the columns be as well? Having predictable ordering - possibly configurable and not necessarily strictly alphabetical - in the schema file should help with consistency, and therefore readability, as well. Something like foreign keys at the top, timestamps at the bottom (before indexes), and everything else in the middle would make a lot of sense for me personally.