# Custom commands to use with repository's commands macro

**URL:** <https://discourse.rom-rb.org/t/custom-commands-to-use-with-repositorys-commands-macro/451>\
**Category:** Issues\
**Created:** [April 11, 2021, 7:16am UTC](https://discourse.rom-rb.org/t/custom-commands-to-use-with-repositorys-commands-macro/451 "2021-04-11T07:16:09Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![lowski](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.rom-rb.org/lowski/32/230_2.png) [@lowski](https://discourse.rom-rb.org/u/lowski)\
**Post date:** [April 11, 2021, 7:16am UTC](https://discourse.rom-rb.org/t/custom-commands-to-use-with-repositorys-commands-macro/451/1 "2021-04-11T07:16:09Z")

</div>

Hi there!  
I’ve been going through [commands guide](https://rom-rb.org/learn/core/5.2/commands/), but I can’t find a any info on how to build a generic command that can be registered on a repository similarly to built-in `create`, `update`, and `delete` commands. Is it possible to do?

Another semi-related question - is there a way to provide a base class for all repository classes? Let’s say I’d like to have methods defined on all my repositories without using mixins or monkey-patching `ROM::Repository::Root` class. Is that possible?

Thank you in advance for answering my questions.

PS. Sorry if they might trivial but I’ve just stared looking into ROM.rb, and still finding my ways around docs, and guides.

---

<div class="post-metadata">

**Author:** ![solnic](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.rom-rb.org/solnic/32/279_2.png) [@solnic](https://discourse.rom-rb.org/u/solnic)\
**Post date:** [April 14, 2021, 8:58am UTC](https://discourse.rom-rb.org/t/custom-commands-to-use-with-repositorys-commands-macro/451/2 "2021-04-14T08:58:42Z")

</div>

> [@lowski](#):
>
> I’ve been going through [commands guide](https://rom-rb.org/learn/core/5.2/commands/), but I can’t find a any info on how to build a generic command that can be registered on a repository similarly to built-in `create` , `update` , and `delete` commands. Is it possible to do?

Yes it is possible although it’s a bit weird because the name of the method must match the command identifier. So, in case of the built-in commands you have `commands :create` that translates to a corresponding `:create` command.

This means that if you register a custom command and name it, let’s say, `:upsert`, then you should be able to do `commands :create, :upsert` and both `command` and `upsert` methods should become available in your repository.

> [@lowski](#):
>
> Another semi-related question - is there a way to provide a base class for all repository classes?

Yes, you actually should have an abstract repository class that inherits from `Root` and use that in your repo classes. Here’s how it looks in one of my projects:

```ruby
module Devtools
  class Repository < ROM::Repository::Root
    include Deps[container: "persistence.rom"]

    struct_namespace Structs
  end
end

```

Then I have my repos that inherit from it, ie:

```ruby

require "devtools/repository"

module Devtools
  class PullRequestRepo < Repository[:pull_requests]
    # stuff
  end
end

```

Hope this helps. Lemme know if I should explain it better 🙂

---

<div class="post-metadata">

**Author:** ![lowski](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.rom-rb.org/lowski/32/230_2.png) [@lowski](https://discourse.rom-rb.org/u/lowski)\
**Post date:** [April 14, 2021, 3:58pm UTC](https://discourse.rom-rb.org/t/custom-commands-to-use-with-repositorys-commands-macro/451/3 "2021-04-14T15:58:18Z")

</div>

@solnic thanks for the reply. Base class for repository works fine!

I have a problem with custom command though. Can you provide a working example for ROM.rb with rails?

I’ve tried something like this (registered with `commands :build` on the repo):

```auto
class BuildCommand < ROM::SQL::Commands::Create
  relation :projects
  register_as :build

  def execute(tuple)
    # do whatever you need
  end
end

```

but it throws error when I try to use it:

```auto
ArgumentError: wrong number of arguments (given 1, expected 2+)
from vendor/bundle/ruby/2.7.0/gems/rom-core-5.2.5/lib/rom/command.rb:475:in `apply_hooks'

```

PS. It also does not work without `relation :projects` so it’s not generic.

---

<div class="post-metadata">

**Author:** ![solnic](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.rom-rb.org/solnic/32/279_2.png) [@solnic](https://discourse.rom-rb.org/u/solnic)\
**Post date:** [April 16, 2021, 8:50am UTC](https://discourse.rom-rb.org/t/custom-commands-to-use-with-repositorys-commands-macro/451/4 "2021-04-16T08:50:35Z")

</div>

Does it work if you manually do `projects.command(:build).call(some_data)`?

---

<div class="post-metadata">

**Author:** ![lowski](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.rom-rb.org/lowski/32/230_2.png) [@lowski](https://discourse.rom-rb.org/u/lowski)\
**Post date:** [April 16, 2021, 5:26pm UTC](https://discourse.rom-rb.org/t/custom-commands-to-use-with-repositorys-commands-macro/451/5 "2021-04-16T17:26:09Z")

</div>

@solnic it works fine. However `ProjectRepository.new(ROM.env).root.mapper.model` gives me the correct entity class, while `relation.mapper` in the `ROM.env.relations[:projects].command(:build).call(some_data)` returns `false`.

To give you more context, I was following Exploding Rails book and I wanted to have a custom `build` command that creates an empty entity that I can use with Rails form helpers.

If I define `build` method on the base repo class like this:

```ruby
def build(attributes = {})
  root.mapper.model.new(attributes)
end

```

It all works fine. However I wanted to inject to the repo via custom `build` commands like this: `commands :build, :create, update: :by_pk, delete: :by_pk`.

---

<div class="post-metadata">

**Author:** ![solnic](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.rom-rb.org/solnic/32/279_2.png) [@solnic](https://discourse.rom-rb.org/u/solnic)\
**Post date:** [April 19, 2021, 12:44pm UTC](https://discourse.rom-rb.org/t/custom-commands-to-use-with-repositorys-commands-macro/451/6 "2021-04-19T12:44:28Z")

</div>

This is because repository relations are configured to use auto-struct mapping. You need to give me more context (code-wise) so that I can tell you what to do. ie how your command is defined.

---

<div class="post-metadata">

**Author:** ![lowski](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.rom-rb.org/lowski/32/230_2.png) [@lowski](https://discourse.rom-rb.org/u/lowski)\
**Post date:** [April 19, 2021, 5:09pm UTC](https://discourse.rom-rb.org/t/custom-commands-to-use-with-repositorys-commands-macro/451/7 "2021-04-19T17:09:14Z")

</div>

@solnic thanks again. Here is the repository with working code and TODO comments with what I want to achieve - [Placeholder for switching to build commands by lowski · Pull Request #1 · lowski/exploding-rails · GitHub](https://github.com/lowski/exploding-rails/pull/1) (I’ve opened a PR with `TODO` comments so it’s easier for you to understand my goals), and also see the full application (it’s basically app built with [exploding-rails](https://leanpub.com/maintain-rails) with some of my own modifications).

Feel free to reply in the PR if that’s what you prefer. Thank you once again for taking the time to look into this for me 🙇‍♂️ .

---

<div class="post-metadata">

**Author:** ![solnic](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.rom-rb.org/solnic/32/279_2.png) [@solnic](https://discourse.rom-rb.org/u/solnic)\
**Post date:** [April 21, 2021, 5:30am UTC](https://discourse.rom-rb.org/t/custom-commands-to-use-with-repositorys-commands-macro/451/8 "2021-04-21T05:30:14Z")

</div>

@lowski oh I see now what you’re after - I don’t recommend doing this at the command level. Commands are meant to be used for db-specific stuff. Model instantiation should be handled by repositories. I’ll be adding some convenient APIs for that in 6.0.0. Probably something like `RootRepository#build` would make sense.

---

<div class="post-metadata">

**Author:** ![lowski](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.rom-rb.org/lowski/32/230_2.png) [@lowski](https://discourse.rom-rb.org/u/lowski)\
**Post date:** [April 22, 2021, 3:18pm UTC](https://discourse.rom-rb.org/t/custom-commands-to-use-with-repositorys-commands-macro/451/9 "2021-04-22T15:18:09Z")

</div>

Got it, thanks! In this case I will stick to the method on the `ApplicationRepository`.
