ROM 5.0 Roadmap


#1

Hey folks,

We’ve got a roadmap for version 5.0 and I’d like to summarize what we’re planning to do in this next major upgrade. Here we go:

rom-core:

  • Abstract caching API - adapters will be able to implement caching strategies with pluggable caching backends (memcached, redis, whatever you want)
  • Support for identity map - mappers will be instantiating only unique structs, this will be supported in adapters where a struct can be identified by a unique key. It should give us major performance boost, and it’ll be more correct too
  • Void-return commands - this will allow you to define commands that do not return any results
  • More configuration/setup events - this will make writing plugins more flexible
  • Pagination plugin with an abstract API, so that adapters can implement it
  • [experimental] support for resolving execution order for commands produced by combined relations - this will allow doing things like tasks.combine(:user).command(:create).call(title: “Task”, user: { name: “Jane” }) where rom has to figure out that user must be persisted first, then task
  • [experimental] support for update/delete commands in combined relations - currently only create is supported

rom-mapper:

  • Attribute DSL will be removed in favor of transformer API (which is basically transproc DSL)
  • Mapper compiler will translate relation ASTs directly to transproc mapping functions, w/o the overhead of building up attributes

rom-repository:

  • Plugin API
  • Plugins:
    • support for defining a default relation view in root repos, ie view :active on a user repo, would use Users#active as the default view used by this repo. Kinda like default scope in AR, but better, since relations stay the same, and you only restrict access at the repo level
    • 1st-class support for changesets, so that you can configure changeset namespace, and repos will figure out which custom changeset class should be used
    • elasticsearch support (reminder: we’ve got a sweet rom-elasticsearch adapter) - this will provide conventional usage for working with ES

rom-changeset:

  • Plugin API (hard to say at this point if we’ll add some plugins, but the API will be in place)
  • Improved support for associations, it’s not fully defined yet but there are some use cases we don’t support yet, so we want to address that
  • More built-in mapping functions, that will cover various common use cases

Another general change will be to inline version number for all gems, which means rom, rom-core, rom-mapper, rom-changeset and rom-repository will be bumped to 5.0.0.

Let us know what you think, if we missed something important, or you think this is too much :wink: I’ll be adding issues describing individual tasks, in case somebody would like to help with development.

We’ll announce rom-sql 3.0 roadmap soon too :slight_smile:

Cheers!


#2

#3

What about the support for dry-auto_inject? I haven’t checked that recently, but there was a problem with the repository constructor which accepted rom instance, when dry-auto_inject uses kw-arguments.

More importantly - will you be working with Luca on adjusting the releases of ROM and Hanami? I know it’s not a problem of ROM per se, but at present Hanami uses ROM v. 3 which is a bit outdated, so adjusting the releases of these tools would be a major improvement.


#4

I’m actually not 100% sure if we want to make repos open to DI. I’m worried this would encaurage people to make repos responsible for too many things. I’ve never had the need to inject anything to a repo (FWIW). It would be good to discuss this further, see what kind of use cases people have and then decide. It’s not going to be a difficult change to make, so we can take it easy.

Both teams are in touch all the time. We will work together on new hanami-model. I already made hanami-model work with rom 4.x (gotta finally push it to a branch :sweat_smile:), but I suppose hanami 2.0 would upgrade to rom 5.0 already.


#5

Well, interesting point. I needed that in the early days of my acquaintance with ROM - namely, I wanted to use one repository in the other, in order to use some non-trivial query in the first one, thus using DI seemed to be the best idea. What do you think about that? Would you expose only the basic operations needed to retrieve the objects (structs?) and combine them via transproc in some higher layer? This seems like too much abstraction for me (i.e. repository over two other repositories).

Great to hear that! Looking forward for the merge.


#6

Complex queries should be encapsulated by relations, not repositories. Composing repos from other repos seems weird. This means if you’ve got a complex piece of query logic, hide it behind relation interface, then re-use across many repos.


#7

One use case I can consider is multi-tenancy, or state filters: Given a particular ID, I want to ensure that the query always adds that to relation queries. It’s better to inject that when the repository is created than it is to have to remember to provide it in every method that may be called on that repository.


#8

Could you start a new thread with some code ideas? I’m not sure if I understand what you’d like to have :slight_smile: