Skip to content

Commit

Permalink
Support standard as interface for command graph too
Browse files Browse the repository at this point in the history
  • Loading branch information
solnic committed Jun 1, 2015
1 parent 133652e commit bd4757e
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 5 deletions.
12 changes: 12 additions & 0 deletions lib/rom/commands/abstract.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ def lazy?
false
end

# @api private
def graph?
false
end

# Target relation on which the command will operate
#
# By default this is set to the relation that's passed to the constructor.
Expand All @@ -125,6 +130,13 @@ def target
relation
end

# Return name of this command's relation
#
# @api private
def name
relation.name
end

# Assert that tuple count in the target relation corresponds to :result
# setting
#
Expand Down
39 changes: 35 additions & 4 deletions lib/rom/commands/graph.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'rom/pipeline'
require 'rom/support/options'
require 'rom/commands/graph/class_interface'

module ROM
Expand All @@ -9,6 +10,7 @@ module Commands
class Graph
extend ClassInterface

include Options
include Pipeline
include Pipeline::Proxy

Expand All @@ -21,8 +23,11 @@ class Graph
alias_method :left, :root
alias_method :right, :nodes

option :mappers, reader: true, default: proc { MapperRegistry.new }

# @api private
def initialize(root, nodes)
def initialize(root, nodes, options = {})
super
@root = root
@nodes = nodes
end
Expand All @@ -48,10 +53,17 @@ def call(*args)
left = root.call(*args)

right = nodes.map do |node|
if node.lazy?
node.call(args.first, left)
response =
if node.lazy?
node.call(args.first, left)
else
node.call(left)
end

if node.result.equal?(:one) && !node.graph?
[response]
else
node.call(left)
response
end
end

Expand All @@ -61,6 +73,25 @@ def call(*args)
[left, right]
end
end

# Return a new graph with updated options
#
# @api private
def with(new_options)
self.class.new(root, nodes, options.merge(new_options))
end

# Return name of the root relation
#
# @api private
def name
root.relation.name
end

# @api private
def graph?
true
end
end
end
end
9 changes: 8 additions & 1 deletion lib/rom/env.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,14 @@ def command(options)
commands[name]
end
when Array
Commands::Graph.build(commands, options)
graph = Commands::Graph.build(commands, options)
name = graph.name

if mappers.key?(name)
graph.with(mappers: mappers[graph.name])
else
graph
end
else
raise ArgumentError, "#{self.class}#command accepts a symbol or an array"
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,44 @@ def execute(tuples, user)
{ name: 'blue', task: 'Task Two' }
])
end

it 'works with auto-mapping' do
setup.mappers do
define(:users) do
register_as :entity
reject_keys true

model name: 'Test::User'

attribute :name

combine :task, type: :hash, on: { name: :user } do
model name: 'Test::Task'
attribute :title
end
end
end

setup.commands(:tasks) do
define(:create) do
input Transproc(:accept_keys, [:title, :user])
result :one

def execute(tuple, user)
super(tuple.merge(user: user.fetch(:name)))
end
end
end

input = { user: { name: 'Jane', task: { title: 'Task One' } } }

command = rom.command([
{ user: :users }, [:create, [{ task: :tasks }, [:create]]]
]).as(:entity)

result = command.call(input).first

expect(result).to be_instance_of(Test::User)
expect(result.task).to be_instance_of(Test::Task)
end
end

0 comments on commit bd4757e

Please sign in to comment.