Commands on repos vs changesets on relations

As stated in How do you set timestamps in version 4.0? - #7 by buszu, since v4 changesets are available directly on relations. The documentation at ROM - Commands says:

For consistency, you should consider using changesets instead of commands

However, the repositories documentation ROM - Quick Start describes only commands. Does it mean that if I want additional changesets functionality (for example, :add_timestamps), I need to create a record via relation, not repo? So, given I have a repo with commands configured, instead of

users_repo.create(name: 'foo')

I now need to do more verbose

users_repo.users.changeset(:create, ...).map(:add_timestamps).commit

? Is going through relations a recommended approach now?

Oh, no - it’s just that in repos you can use changesets instead of commands. I’ll be adding a changeset plugin to repos in 6.0 so this will become clearer. Not sure if we event want to keep commands plugin enabled by default. Thanks for pointing this out.

I see. So in 6.0 there’s be a declarative way via a plugin. And for now I can do something like this in a repo:

class ContractRepository < ROM::Repository::Root
  # ...
  def upsert(id, attrs)
    changeset =
      if id
        root.by_pk(id).changeset(:update, attrs)
        root.changeset(:create, attrs)

@ineu correct :slightly_smiling_face: In 6.0 we may end up having something like this:

class ContractRepository < ROM::Repository[:contracts]
  use :changesets, command: :upsert

  def upsert(id, attrs)
    contracts.changeset(:upsert, id, attrs).commit

This is just a rough idea. There are many common scenarios that can be covered through a plugin that provides pre-configured changeset classes that you won’t have to deal with directly.

1 Like