Skip to content

Instantly share code, notes, and snippets.

@adz
Last active February 4, 2017 10:26
Show Gist options
  • Save adz/660bf55fc2c822dff86f to your computer and use it in GitHub Desktop.
Save adz/660bf55fc2c822dff86f to your computer and use it in GitHub Desktop.
command_builder = rom.command # no relation given, so get builder
nested_command = command_builder.create(user: :users) do |user|
user.create(:books)
end
# equivalent:
nested_command = rom.command({user: :users}, [:create, [:books, [:create]]])
# equivalent
user_create = rom.command(:users)[:create]
books_create = rom.comand(:books)[:create]
nested_command = -> input {
user_create.call(input[:user]).combine(
books_create.call(input[:user][:books])
)
}
# and books_create command is built to take (books, user)
# and gets partially applied with :books, so on combine
# it receives output of user_create command, which will be a user
@adz
Copy link
Author

adz commented Jan 13, 2016

ROM Commands

The Command Registry holds commands for one relation
The Container holds Command Registries (looked up by relation)

rom.command(<relation_name>)
 => CommandRegistry

Inside Command Registry you access defined commands:

rom.command(<relation_name>)[<command_name>]

Method missing works too:

rom.command(:users).create # same as:
rom.command(:users)[:create]

These commands must be given their input as for the relation, so typically a hash, or an array of hashes. It’s defined in #execute of the command.

Combining commands — the fun stuff :)

Want to combine multiple relations/commands.
We have ‘combine’

   create_user = rom.command(:users).create
   create_task = rom.command(:tasks).create

   command = create_user
     .with(name: 'Jane')
     .combine(create_task.with(title: 'Task’))

HOW does it work? Combine just passes through output of left to right…
and it’s been partially applied with task,
and command is defined to take (task, user)

GRAPH commands

In practice input given will be nested too, so want to provide a ‘path’ into the input for some commands.

rom.command(<graph_definition>)

This <graph_definition> is an array of relation and command lookups, where the relation can be given with associated input path.
Relation name is assumed a key as input path if none given...

Example:

{
  users: [
    {  
      name: ‘Bob’,
      tasks: [ { title: ‘My job’ } ]
    }
  ]
}
rom.command([{users: :users}, [:create, [:tasks, [:create]]]])

# So this:
rom.command([{users: :users}, [:create])
# is same as this:
rom.command(:users)[:create]

# Seems like if not an array, is assumed opts to command… maybe this?
rom.command(:users, update: :active)

Graph DSL

THEN there’s graph DSL

command_builder = rom.command   # no relation given, so get builder
nested_command = command_builder.create(user: :users) do |user|
  user.create(:books)
end

# equivalent:
nested_command = rom.command({user: :users}, [:create, [:books, [:create]]])

# equivalent
user_create = rom.command(:users)[:create]
books_create = rom.comand(:books)[:create]
nested_command = -> input {
  user_create.with(input[:user]).combine(
    books_create.call(input[:user][:books])
  )
}

# and books_create command is built to take (books, user)
# and gets partially applied with :books, so on combine
# it receives output of user_create command, which will be a user

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment