Rom 4.0 roadmap draft


Hey folks!

Last month rom 3.0.0 was released with a ton of improvements, but software is never finished so let’s take a look at our rough ROADMAP for 4.0.0. This is not set in stone yet, and is a subject for a discussion, hence I’m posting it here first before adding specific issues.

OK here we go:

rom 4.0.0

Main focus of this release is improving UX and cleaning up rom-repository by porting its features to the rom core gem (which means that rom core APIs will become more powerful as a bonus).

  • Disable relation inference by default (don’t confuse with schema inference). This feature is cool, but it bites people very often, because when config is borked and your relation classes are not loaded, rom will still infer all relations from your database. This confused and annoyed so many people that this feature must be disabled by default. I don’t think deprecating it is worth the hassle though, so I’d propose to just change it in 4.0.0, because enabling it to maintain backward compatibility costs nothing. Let me know if you disagree.
  • Make auto_registration more flexible - we have 3 strategies, but people clearly need more, so let’s add them. Details are yet to be specified
  • 1st class Association API for all adapters. That’s right. We’re going to have Association API that every adapter will be able to implement (and yes, they will work cross-adapters)
  • Mapper-related features (DSL/setup code) will be moved to rom-mapper
  • Support for passing options to plugins via use :some_plugin, some: :options
  • Rename Relation#combine => Relation#graph because it says what it does. I never liked combine name but it was discussed and folks proposed combine and I agreed. So here I am proposing to rename it after all. This is a low-level API and should have a name that’s less confusing, especially that combine is overridden by repository proxies and it shouldn’t do that
  • Port repository relation proxy features to ROM::Relation:
    • Relation#to_ast which returns an AST representation of a relation
    • Relation#map_with should work the same as in repo proxies, which means it should be able to generate a mapper if a relation was configured to do so via Relation.auto_map option
    • Relation::Graph#to_ast should return the same structure as repo proxies
    • Add Relation::Wrap as a 1st class relation type. These relations represent a relation that’s embedded inside another relation. In SQL land this means a join that adds new attributes to a relation from another one. ie tasks.join(users) will return Relation::Wrap(users, tasks). We can use this to explicitly represent such construct and be able to infer mappers from it. This is what repo proxies already do but it’s missing an explicit representation. Furthermore, other adapters will be able to provide a specialization of this relation so it can be handled in different ways, depending on what a given persistence backend can do.
    • Import CommandCompiler and make it a 1st class API. Repos will simply use it, it’s cool to have it as a standalone first class object because both repos and changesets will be able to use it easily. Right now repos provide it for changesets, which is not so great

rom-mapper 1.0.0

This release will include features ported from rom core, that are specific to setting up rom mappers in rom and also:

  • Switch default DSL to use transproc transformer DSL
  • Move current DSL to an opt-in feature
  • Add a new type of transformation that can merge parent hashes into child hashes, this is needed to improve performance of ManyToOne

rom-sql 2.0.0

  • Introduce run-time association objects. Currently associations are static objects with configuration, they receive relation registry at run-time and calculate same things all over again. We can separate association configuration from run-time association objects (that can be built using the configuration) and these objects not only can be faster, but can also validate if the configuration is correct. Setting up associations can be tricky, and we can improve this by raising meaningful errors when something wasn’t set up correctly. Furthermore, we can infer various options via run-time associations when they are initialized, because we have access to relations at that point.
  • Improve ManyToOne so that instead of adding virtual FKs to parent tuples, we’ll simply return all parents for specific children, and use a new type of in-memory transformation to merge children with their parents (see rom-mapper 1.0 roadmap too)
  • Introduce auto-migrations - relation schemas will be used to create migrations automatically that will sync your database schema with your relation schemas. This of course requires using explicit schema definitions instead of using inference. This will work in a similar way as in DataMapper.

rom-repository 2.0.0

This release will be a huge clean up since a lot of its features will be ported to core. At this point it’s hard to say what kind of new features will be added though. One thing to consider is extracting Changeset into rom-changeset gem, because it’s a huge feature and will be growing very fast.

That’s more-or-less it. If you feel like something is missing please let me know in this thread. If you disagree with something, let me know as well and we can discuss. I’ll start working on adding issues describing individual changes/features/refactors, once we feel confident that this makes sense :slight_smile:

Once we have the roadmap finalized, with issues reported describing what needs to be done, we can start the fun work. Rough ETA for this release is June. Once the work starts, we’ll cut release branches for on-going maintenance, and master branches will be switched to a minefield, I mean a place where new, hot stuff is happening.



Auto migrations are a tricky thing; while it sounds like a good idea, in theory, it can fall down pretty hard in the case of a legacy or shared database. Also, I’ve wired up at least one app with two separate relations that are rooted in the same table – this was pre-views, but since I also wanted the two relations queried differently, it’s not totally unthinkable even with views.

Certainly, you can avoid autogenerating migs in those cases, and maybe if column drops are never generated … mostly, it strikes me as one of those things that’s kind of like the auto-inferring the existence of a relation. Useful in a bunch of cases, but quite capable of becoming really painful if you stray off the happy-path.


I should clarify that auto-migrations are meant to be a development tool (as in, used when developing a new feature which needs changing schema). I agree this is a tricky thing, but I’d like to give it a shot because even buggy/messy implementation in DataMapper was already very useful, and I believe we can do it better now, because we have a good foundation (schemas with attributes and their types).


This looks great!

So long as the documentation + error messages make it super obvious what is meant to be happening with regards to removing relation inference by default.


@cflipse I’ll be working on migrations, I’m definitely the right person for the job. I have a lot of expertise in this field and will try to handle all the cases. However, any feedback and proposals on that are welcome.

Using automigrations will also help a user to build a right DB model, for instance indexing all FKs by default is a good design choice, so we can advise it with warnings or something like that.