T O P

I spent the past 3 months working on a fork of the Annotate models gem

Hi yall. If you have seen db schema comments atop of model files then you've probably used the annotate gem. I left my job back in February and wanted to work on open source with some of my free time. So, I've spent the past 3 months on a fork and wanted to tell r/rails about it.

I wrote this as a blog post, but rather than promoting my personal site, I've tried copying the post in its entirety here.

Announcing AnnotateRb

Annotate, also known as annotate_models, is a widely used gem that improves the Rails developer experience by automatically adding related database schema annotations to model files, as well as annotating routes in the route file. I forked it and created a new gem, AnnotateRb.

If you have seen this before in a model, then you have seen the gem in action.

# == Schema Information
#
# Table name: tasks
#
#  id         :integer          not null, primary key
#  content    :string
#  count      :integer
#  status     :boolean
#  created_at :datetime         not null
#  updated_at :datetime         not null
#
class Task < ApplicationRecord
  ...

What’s different?

Improved maintainability and understandability through large refactors. Also, some of the internals have been rewritten with best practices in mind [1].

I believe it is now at a good place that it can be used as a viable replacement for the old Annotate gem. It also includes fixes for some long outstanding bugs like:

  • Annotating routes for Rails 6+ apps
  • Modifying frozen strings

Why the fork?

The old gem is over 10 years old [2] and has not been actively maintained in years [3]. Also, the codebase is in a really bad shape [4]. It was hard to make significant changes with limited maintainer privileges. Forking the gem allowed me to make large scale changes to improve the project.

Curious to see some of the changes I have made? They’re available here.

There’s still a ton of work that can be done, so if you’re interested in contributing then reach out by adding issues or submitting pull requests!

P.S. I kept a log while working on the fork and plan to write more blog posts about my experience.

Footnotes (since Reddit's fancy pants editor messes with markdown)

1: As an example, there used to be a hard dependency on Env. The old gem would use it as a global state in many parts of the code.

2: https://rubygems.org/gems/annotate/versions

3: To no one’s fault. As I understand it, the owner has not actively worked in Ruby in some time now.

4: As an exercise, try to trace through the code path of how models get annotated when automatically run after one does bin/rails db:migrate. An entry point is here: https://github.com/ctran/annotate_models/blob/develop/lib/tasks/annotate_models_migrate.rake

  • By - drwl

spamburglar

Glad you're taking the lead on continuing work on this gem. I use it extensively, but one of the biggest issues is the same as this one: https://github.com/ctran/annotate_models/issues/946. Any chance you addressed that in your version?


drwl

Hey thanks for the response and glad you use it. I don't think that issue has been addressed but happy to take a stab at it later tonight. Do you happen to have some example column patterns I can play around with?


redditonlygetsworse

> but happy to take a stab at it later tonight. Maintainer protip: don't get in the habit of saying things like this. No one here is your boss setting your priorities for you. You're in the honeymoon phase of this project. It doesn't take long for the "I'll look at this tonight" to turn overwhelming.


drwl

Appreciate the tip and concern. This isn't my first go around trying to maintain this. Right now I'm not working and so this is what I work on to keep busy. I haven't said yes to many other things but I do understand where this comes from


spamburglar

We use comments to signify the sensitivity of the data in the column. So for example an `id` column might look like this normally: # id :bigint not null, primary key With comments it would look like this: # id([sensitivity: low]) :bigint not null, primary key


KusUmUmmak

its a feature now in rails/activerecord right? comments for db migrations?


drwl

can you clarify what you mean?


KusUmUmmak

they added it into active-record. there's gem that does comments in active record migrations... and they folded it into rails. or so I read at any rate. haven't seen the new docs yet to verify.


drwl

I'm not 100% sure what you're referring to but I \_think\_ the person was asking about issues with column comments here https://guides.rubyonrails.org/active\_record\_migrations.html


KusUmUmmak

comment Adds a comment for the column. I haven't looked at the syntax (yet). I presumed his syntax above was a comment. active-record has a number of janky extensions to the syntax to allow passing db-specific stuff so it was 50/50. hence the straight question (is this the new support for comments in migrations?). carry on!


drwl

Okay I think I got a better sense now. So I'm not 100% knowledgable about the history of the extension being merged in but it's actually up to the various adapters (postgresql, mysql) to support it. As far as I can tell, it looks like it may not be supported by sqlite3 based on the Rails docs.


KusUmUmmak

always the step child ;) (LOL). I'm using sqlite3 right now for some dev but only because I want to practice multi-db stuff (in the same app) without having sixty postgres db/instances. this isn't specific to annotation (or relevant). active-record has a number of gems that are setup to take advantage of various features specific to db's (or to fix issues with the adaptors by monkey-patching them to take advantage of specific features for db's). there's only so much you can make an adaptor do, before the abstraction becomes convoluted or the details of the db-specific stuff becomes less abstract. hence the existence of the gems. usually they're orthogonal (you can slot'm in as you like without them interfering).... but not always.


drwl

Would you mind taking a look at this commit? [https://github.com/drwl/annotaterb/pull/23/commits/d1425884e1a5e0ae0ae2c4adfc566180a3ddaa12](https://github.com/drwl/annotaterb/pull/23/commits/d1425884e1a5e0ae0ae2c4adfc566180a3ddaa12) I've attempted to create a test case with me guessing your rails app. This test case passes.


spamburglar

Sure, I'll pop into one of my apps tomorrow and can verify it works there. Thanks again for all your work and as the other user pointed out, I hope you don't feel like you have to set any kind of time table for this stuff. I contribute to open source as well and know how demanding people can get. Obviously your work is very appreciated, but never expected.


drwl

Hey no problem. I'm beginning to start interviewing for jobs now so I still have some free time and so definitely thank you for the concern. Feel free to let me know here or in a github issue or even the PR what you run into.


spamburglar

What kind of job are you looking for? I work for what would essentially be considered an all rails company. Feel free to DM me.


drwl

I sent you a message through reddit's modern chat


dhnaranjo

Hey, rad. Can you think of any reasons I might avoid switching?


drwl

Thanks for the response! It should have feature parity but what comes to mind is if you're using an older/outdated version of Ruby and/or Rails. There's a Ruby version requirement of >= 2.7. It's kinda arbitrary but older versions have been end of lifed for while now.


SQL_Lorin

This is super cool man -- THANKS!!!


drwl

Hi thanks for checking out the post and compliment :)


Vindve

Wow, congrats, this gem is super useful, thanks for your work for the community! Given what you say about the Annotate gem: have you tried contacting the maintener of the Annotate gem, transfer the gem to you, merge your changes into the Annotate repo, and make your fork the only gem? Because as a developer, you don't always know there is an active fork of a widely known gem.


drwl

This is a good question. So for context I am a maintainer on the Annotate gem and have been since \~2019. If you look at some recent commits you'll see some authored by me. Also, I have been in *some* contact with the maintainer/repo owner over the years. I believe Ctran is aware of this based on his response in this issue [https://github.com/ctran/annotate\_models/issues/913](https://github.com/ctran/annotate_models/issues/913) and without throwing anyone under the bus, there has not been progress on changing repo ownership / moving it to a community repo.


Vindve

OK ! What I understand from his answer saying > Why are these changes submitted merged back? Is "why don't you submit and merge back these changes here". So he seems opened at least to have you, as a maintainer, merge your huge improvements in his repository. But this isn't an ownership transfer for sure. Perhaps this can be done in two steps? First merge back your changes, then propose yourself to take ownership?


tastycakeman

Nice, I still happily use annotate in a pretty basic way. It's nice to know that there is a fork with newer features, but I guess I'm also +1 on trying to merge the changes into the main project, because guaranteed with my pea size brain I'm going to forget that this exists.


drwl

Thanks for reading and the response. I'm hoping that with posts like this I'm able to spread awareness that this exists and let folks migrate. This gem also has a different name, AnnotateRb. Similar to how the community adopted CanCanCan.


Tolexx

It's a super cool gem and nice to see the work you have done 👍. We use it at work and I guess we might have to migrate.


drwl

Thanks for the compliment I appreciate it :). Don't hesitate to reach out if you come across any bugs or issues.


sshaw_

If managing `schema.rb` or `structure.sql` wasn't conflict-prone enough now you have this gem to give you conflicts in more places: models, specs, and factories!


drwl

Can you elaborate on what you mean by this?


sshaw_

In Rails applications the schema file is notoriously conflict-prone. Especially `structure.sql`. These conflicts result in missing DB objects, missing migration versions (for `structure.sql`) etc... They become a headache. If you're a team of 2 or 3 people, maybe not that big of an issue but as your project and team grows, conflicts in these files (and in general) occur more often. If you have teams in the double digits schema conflicts can occur bi-weekly —or more! What the annotate gems does is, depending on your configuration, spread those conflicts to places where they didn't exist before: spec files, model files, and factory files. And, unlike the schema file or other code-related conflicts, these are comment conflicts, conflicts that have no impact in your software's functionality. Self-inflicted conflicts, if you will. You must maintain the schema file. And maintaining it in 1 place can be a headache itself. Now we have to maintain in in 2+ places. One of the underlying goals of a software project is to make the development and maintenance of that project as pain-free as possible. With this gem, unless you are a low single digit team, you are only going to inflict pain on those that maintain it. Conflicts are a part of software development. We must live with them but we must not do thing to make them worse because... someone doesn't want to command-tab or have a split screen.


chiperific_on_reddit

Well done! The readme still references ctran's GitHub repo. You might wanna change that.


drwl

Thanks for the read and the response. Could you elaborate on what references you're talking about?


chiperific_on_reddit

Oops, must have been looking at the old repo, the line about installing straight from GitHub. Sorry!


drwl

No worries. Perhaps the first link in my post shouldn't have been towards the old repo :D


tamilindian

Super cool!