patch 0.4.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +13 -0
- data/README.md +176 -0
- data/bin/patchrb +40 -0
- data/lib/patch/config.rb +124 -0
- data/lib/patch/em_patch.rb +47 -0
- data/lib/patch/hub.rb +68 -0
- data/lib/patch/io/midi/action.rb +42 -0
- data/lib/patch/io/midi/input.rb +110 -0
- data/lib/patch/io/midi/message.rb +112 -0
- data/lib/patch/io/midi/output.rb +58 -0
- data/lib/patch/io/midi.rb +45 -0
- data/lib/patch/io/module.rb +35 -0
- data/lib/patch/io/osc/action.rb +43 -0
- data/lib/patch/io/osc/client.rb +60 -0
- data/lib/patch/io/osc/message.rb +109 -0
- data/lib/patch/io/osc/server.rb +159 -0
- data/lib/patch/io/osc.rb +43 -0
- data/lib/patch/io/websocket/node.rb +103 -0
- data/lib/patch/io/websocket/socket.rb +103 -0
- data/lib/patch/io/websocket.rb +27 -0
- data/lib/patch/io.rb +15 -0
- data/lib/patch/log.rb +97 -0
- data/lib/patch/message.rb +67 -0
- data/lib/patch/node/container.rb +69 -0
- data/lib/patch/node/map.rb +71 -0
- data/lib/patch/node.rb +10 -0
- data/lib/patch/patch.rb +59 -0
- data/lib/patch/report.rb +132 -0
- data/lib/patch/thread.rb +19 -0
- data/lib/patch.rb +42 -0
- data/test/config/nodes.yml +16 -0
- data/test/config/patches.yml +41 -0
- data/test/config_test.rb +216 -0
- data/test/helper.rb +20 -0
- data/test/hub_test.rb +49 -0
- data/test/io/midi/action_test.rb +82 -0
- data/test/io/midi/input_test.rb +130 -0
- data/test/io/midi/message_test.rb +54 -0
- data/test/io/midi/output_test.rb +44 -0
- data/test/io/midi_test.rb +94 -0
- data/test/io/module_test.rb +21 -0
- data/test/io/osc/action_test.rb +76 -0
- data/test/io/osc/client_test.rb +49 -0
- data/test/io/osc/message_test.rb +53 -0
- data/test/io/osc/server_test.rb +116 -0
- data/test/io/osc_test.rb +111 -0
- data/test/io/websocket/node_test.rb +96 -0
- data/test/io/websocket_test.rb +37 -0
- data/test/js/logger.js +67 -0
- data/test/js/message.js +62 -0
- data/test/js/qunit-1.18.0.js +3828 -0
- data/test/js/qunit.css +291 -0
- data/test/js/test.html +15 -0
- data/test/js/websocket.js +12 -0
- data/test/log_test.rb +96 -0
- data/test/message_test.rb +109 -0
- data/test/node/container_test.rb +104 -0
- data/test/node/map_test.rb +50 -0
- data/test/node_test.rb +14 -0
- data/test/patch_test.rb +57 -0
- data/test/report_test.rb +37 -0
- metadata +320 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
module Patch
|
2
|
+
|
3
|
+
module IO
|
4
|
+
|
5
|
+
module Websocket
|
6
|
+
|
7
|
+
class Node
|
8
|
+
|
9
|
+
attr_reader :id
|
10
|
+
|
11
|
+
# @param [Fixnum] id
|
12
|
+
# @param [String] host
|
13
|
+
# @param [Fixnum] port
|
14
|
+
# @param [Hash]
|
15
|
+
# @option properties [Log] :log
|
16
|
+
def initialize(id, host, port, options = {})
|
17
|
+
@config = {
|
18
|
+
:host => host,
|
19
|
+
:port => port
|
20
|
+
}
|
21
|
+
@id = id
|
22
|
+
@log = options[:log]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Send a message over the socket
|
26
|
+
# @param [Patch::Patch] patch Context
|
27
|
+
# @param [Array<::Patch::Message>] messages A message or messages to send
|
28
|
+
# @return [String, nil] If a message was sent, its JSON string; otherwise nil
|
29
|
+
def puts(patch, messages)
|
30
|
+
if running?
|
31
|
+
unless (messages = [messages].flatten.compact).empty?
|
32
|
+
json = messages.to_json
|
33
|
+
@log.puts("Sending messages: #{json}") if @log
|
34
|
+
begin
|
35
|
+
@socket.puts(json)
|
36
|
+
rescue Exception => exception # failsafe
|
37
|
+
@log.exception(exception) if @log
|
38
|
+
::Thread.main.raise(exception)
|
39
|
+
end
|
40
|
+
json
|
41
|
+
end
|
42
|
+
else
|
43
|
+
@log.puts("Warning: No connection") if @log
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Disable the message listener
|
49
|
+
# @return [Boolean]
|
50
|
+
def disable(patch)
|
51
|
+
@socket.disable
|
52
|
+
end
|
53
|
+
|
54
|
+
# Listen for messages with the given patch context
|
55
|
+
# @param [Patch] patch
|
56
|
+
# @param [Proc] callback callback to fire when events are received
|
57
|
+
# @return [Boolean]
|
58
|
+
def listen(patch, &callback)
|
59
|
+
ensure_socket.on_message do |data|
|
60
|
+
handle_input(patch, data, &callback)
|
61
|
+
end
|
62
|
+
true
|
63
|
+
end
|
64
|
+
|
65
|
+
# Start the websocket
|
66
|
+
# @return [Boolean]
|
67
|
+
def socket
|
68
|
+
ensure_socket
|
69
|
+
end
|
70
|
+
alias_method :start, :socket
|
71
|
+
|
72
|
+
# Is the server active?
|
73
|
+
# @return [Boolean]
|
74
|
+
def active?
|
75
|
+
!@socket.nil? && @socket.active?
|
76
|
+
end
|
77
|
+
alias_method :running?, :active?
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def ensure_socket
|
82
|
+
@socket ||= ::Patch::IO::Websocket::Socket.start(@config)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Handle a received message
|
86
|
+
# @param [String] json_message A raw inputted JSON message
|
87
|
+
# @param [Proc] callback A callback to fire with the received message
|
88
|
+
# @return [Message]
|
89
|
+
def handle_input(patch, json_message, &callback)
|
90
|
+
message_hash = JSON.parse(json_message, :symbolize_names => true)
|
91
|
+
message = Message.new(message_hash)
|
92
|
+
@log.puts("Recieved message: #{message_hash.to_json}") if @log
|
93
|
+
yield(message) if block_given?
|
94
|
+
message
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Patch
|
2
|
+
|
3
|
+
module IO
|
4
|
+
|
5
|
+
module Websocket
|
6
|
+
|
7
|
+
class Socket
|
8
|
+
|
9
|
+
def self.start(config)
|
10
|
+
socket = new
|
11
|
+
socket.start(config)
|
12
|
+
socket
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@onmessage = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def puts(data)
|
20
|
+
@socket.send(data)
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Boolean]
|
24
|
+
def disable
|
25
|
+
@socket.onmessage = nil
|
26
|
+
@onmessage.clear
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param [Proc] callback callback to fire when events are received
|
31
|
+
# @return [Boolean]
|
32
|
+
def on_message(&callback)
|
33
|
+
if @socket.nil?
|
34
|
+
@onmessage << callback
|
35
|
+
else
|
36
|
+
@socket.onmessage { |data| yield(data) }
|
37
|
+
end
|
38
|
+
true
|
39
|
+
end
|
40
|
+
|
41
|
+
# Start the websocket
|
42
|
+
# @param [Hash] config
|
43
|
+
# @return [Boolean]
|
44
|
+
def start(config, &block)
|
45
|
+
EM::WebSocket.run(config) do |websocket|
|
46
|
+
::Thread.current.abort_on_exception = true
|
47
|
+
begin
|
48
|
+
enable(websocket)
|
49
|
+
rescue Exception => exception
|
50
|
+
::Thread.main.raise(exception)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
true
|
54
|
+
end
|
55
|
+
|
56
|
+
# Is the socket active?
|
57
|
+
# @return [Boolean]
|
58
|
+
def active?
|
59
|
+
!@socket.nil?
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
# If callbacks were added before the socket was active, assign them to the socket event handler
|
65
|
+
def configure_message_callbacks
|
66
|
+
@onmessage.each do |callback|
|
67
|
+
on_message(&callback)
|
68
|
+
end
|
69
|
+
@onmessage.clear
|
70
|
+
end
|
71
|
+
|
72
|
+
# Enable this node after initializing an EM::Websocket
|
73
|
+
# @param [EM::Websocket] websocket
|
74
|
+
# @return [Boolean]
|
75
|
+
def enable(websocket)
|
76
|
+
@socket = websocket
|
77
|
+
configure
|
78
|
+
true
|
79
|
+
end
|
80
|
+
|
81
|
+
# Configure the server actions
|
82
|
+
# @return [Boolean]
|
83
|
+
def configure
|
84
|
+
@socket.onopen do |handshake|
|
85
|
+
puts "Connection open"
|
86
|
+
end
|
87
|
+
|
88
|
+
@socket.onclose do
|
89
|
+
puts "Connection closed"
|
90
|
+
end
|
91
|
+
|
92
|
+
configure_message_callbacks unless @onmessage.empty?
|
93
|
+
|
94
|
+
true
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "patch/io/websocket/node"
|
2
|
+
require "patch/io/websocket/socket"
|
3
|
+
|
4
|
+
module Patch
|
5
|
+
|
6
|
+
module IO
|
7
|
+
|
8
|
+
# Websocket IO
|
9
|
+
module Websocket
|
10
|
+
|
11
|
+
# Key that will be used by Patch to identify the module
|
12
|
+
KEY = :websocket
|
13
|
+
extend self
|
14
|
+
::Patch::IO::Module.add(self)
|
15
|
+
|
16
|
+
# Construct a websocket from a node config
|
17
|
+
# @param [Hash] config
|
18
|
+
# @param [Hash] options
|
19
|
+
# @param [Hash]
|
20
|
+
# @option properties [Log] :log
|
21
|
+
def new_from_config(config, options = {})
|
22
|
+
::Patch::IO::Websocket::Node.new(config[:id], config[:host], config[:port], options)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/patch/io.rb
ADDED
data/lib/patch/log.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
module Patch
|
2
|
+
|
3
|
+
# Logging
|
4
|
+
class Log
|
5
|
+
|
6
|
+
# @param [IO] out
|
7
|
+
# @param [Hash] options
|
8
|
+
# @option options [Array<Symbol>] :show
|
9
|
+
def initialize(out, options = {})
|
10
|
+
@out = out
|
11
|
+
@start = Time.now
|
12
|
+
populate_level(options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def path
|
16
|
+
@out.path
|
17
|
+
end
|
18
|
+
|
19
|
+
# The current time since startup
|
20
|
+
# @return [Time]
|
21
|
+
def time
|
22
|
+
Time.now - @start
|
23
|
+
end
|
24
|
+
|
25
|
+
# Output an info message
|
26
|
+
# @param [String] message
|
27
|
+
# @return [String]
|
28
|
+
def puts(message)
|
29
|
+
message = format(message, :type => :info)
|
30
|
+
@out.puts(message) if @info
|
31
|
+
message
|
32
|
+
end
|
33
|
+
alias_method :info, :puts
|
34
|
+
|
35
|
+
# Output an exception
|
36
|
+
# @param [String] exception
|
37
|
+
# @return [String]
|
38
|
+
def exception(exception)
|
39
|
+
if @exception
|
40
|
+
message = format(exception.message, :type => :exception)
|
41
|
+
@out.puts(message)
|
42
|
+
end
|
43
|
+
exception
|
44
|
+
end
|
45
|
+
alias_method :error, :exception
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# Populate the level setting
|
50
|
+
# @param [Hash] options
|
51
|
+
# @return [Debug]
|
52
|
+
def populate_level(options = {})
|
53
|
+
if !options[:show].nil?
|
54
|
+
show = [options[:show]].flatten.compact
|
55
|
+
@exception = !(show & [:exception, :error]).empty?
|
56
|
+
@info = !(show & [:info, :message]).empty?
|
57
|
+
end
|
58
|
+
@exception = true if @exception.nil?
|
59
|
+
@info = true if @info.nil?
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
# Format a message for output
|
64
|
+
# @param [String] message
|
65
|
+
# @param [Hash] options
|
66
|
+
# @option options [Symbol] type
|
67
|
+
# @return [String]
|
68
|
+
def format(message, options = {})
|
69
|
+
{
|
70
|
+
:timestamp => time.seconds.round(2),
|
71
|
+
:caller => caller_method,
|
72
|
+
:message => message,
|
73
|
+
:type => options[:type]
|
74
|
+
}.to_json
|
75
|
+
end
|
76
|
+
|
77
|
+
# Get the caller method where a message originated
|
78
|
+
# @param [Fixnum] depth
|
79
|
+
# @return [String]
|
80
|
+
def caller_method(depth=1)
|
81
|
+
method = caller(depth+1).first
|
82
|
+
parse_caller(method)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Parse the caller name
|
86
|
+
# @param [String] at
|
87
|
+
# @return [String]
|
88
|
+
def parse_caller(at)
|
89
|
+
if /^(.+?):(\d+)(?::in `(.*)')?/ =~ at
|
90
|
+
file = Regexp.last_match[1]
|
91
|
+
file.scan(/.+\/(\w+)\.rb/)[0][0]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Patch
|
2
|
+
|
3
|
+
# A generic controller message
|
4
|
+
class Message
|
5
|
+
|
6
|
+
attr_accessor :index, :patch_name, :value
|
7
|
+
attr_reader :time
|
8
|
+
|
9
|
+
# @param [Hash] properties
|
10
|
+
def initialize(properties = nil)
|
11
|
+
populate_from_properties(properties) unless properties.nil?
|
12
|
+
@time ||= Time.now
|
13
|
+
end
|
14
|
+
|
15
|
+
# Convert the message to a hash
|
16
|
+
# @return [Hash]
|
17
|
+
def to_h
|
18
|
+
properties = {
|
19
|
+
:index => @index,
|
20
|
+
:patch_name => @patch_name,
|
21
|
+
:timestamp => timestamp, #js format
|
22
|
+
:value => @value
|
23
|
+
}
|
24
|
+
properties.merge!(@other_properties) unless @other_properties.nil?
|
25
|
+
properties
|
26
|
+
end
|
27
|
+
|
28
|
+
# Convert the message to a JSON string
|
29
|
+
# @return [String]
|
30
|
+
def to_json(*args)
|
31
|
+
to_h.to_json(*args)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Get the message time as a JS timestamp
|
35
|
+
# @return [Fixnum]
|
36
|
+
def timestamp
|
37
|
+
js_time = @time.to_f * 1000
|
38
|
+
js_time.to_i
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# Populate this message from a hash of properties
|
44
|
+
# @param [Hash] properties
|
45
|
+
# @return [Hash]
|
46
|
+
def populate_from_properties(properties)
|
47
|
+
properties = properties.dup
|
48
|
+
@index = properties.delete(:index)
|
49
|
+
@patch_name = properties.delete(:patch_name)
|
50
|
+
@value = properties.delete(:value)
|
51
|
+
if !(timestamp = properties.delete(:timestamp)).nil?
|
52
|
+
@time = timestamp_to_time(timestamp)
|
53
|
+
end
|
54
|
+
@other_properties = properties
|
55
|
+
end
|
56
|
+
|
57
|
+
# Convert a JS timestamp to a Ruby time
|
58
|
+
# @param [String, Numeric] timestamp
|
59
|
+
# @return [Time]
|
60
|
+
def timestamp_to_time(timestamp)
|
61
|
+
js_time = timestamp.to_f / 1000
|
62
|
+
Time.at(js_time.to_i)
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Patch
|
2
|
+
|
3
|
+
module Node
|
4
|
+
|
5
|
+
# A container for Patch::Node
|
6
|
+
class Container
|
7
|
+
|
8
|
+
include Enumerable
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
attr_reader :nodes
|
12
|
+
def_delegators :@nodes, :all?, :any?, :count, :empty?
|
13
|
+
|
14
|
+
# @param [Array<Object>] nodes
|
15
|
+
def initialize(nodes)
|
16
|
+
@threads = []
|
17
|
+
@nodes = nodes
|
18
|
+
end
|
19
|
+
|
20
|
+
def |(other)
|
21
|
+
@nodes | other.nodes
|
22
|
+
end
|
23
|
+
|
24
|
+
def each(&block)
|
25
|
+
@nodes.each(&block)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Enable the nodes in this container
|
29
|
+
# @return [Boolean]
|
30
|
+
def enable
|
31
|
+
result = @nodes.map { |node| enable_node(node) }
|
32
|
+
result.any?
|
33
|
+
end
|
34
|
+
|
35
|
+
# Get the nodes of the given type
|
36
|
+
# @param [Symbol] :type The type of node (eg :midi)
|
37
|
+
# @return [Array<IO::MIDI, IO::OSC, IO::Websocket>]
|
38
|
+
def find_all_by_type(type)
|
39
|
+
if (mod = IO::Module.find_by_key(type)).nil?
|
40
|
+
[]
|
41
|
+
else
|
42
|
+
@nodes.select { |node| node.class.name.match(/\A#{mod.name}/) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Find the node with the given id
|
47
|
+
# @param [Fixnum] id
|
48
|
+
# @return [IO::MIDI, IO::OSC, IO::Websocket]
|
49
|
+
def find_by_id(id)
|
50
|
+
@nodes.find { |node| node.id == id }
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# Enable the given node
|
56
|
+
# @param [Patch::Node] node
|
57
|
+
# @return [Boolean]
|
58
|
+
def enable_node(node)
|
59
|
+
if node.respond_to?(:start) && !node.active?
|
60
|
+
@threads << ::Patch::Thread.new { node.start }
|
61
|
+
end
|
62
|
+
true
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Patch
|
2
|
+
|
3
|
+
module Node
|
4
|
+
|
5
|
+
# A map of connections between nodes for a given patch
|
6
|
+
class Map
|
7
|
+
|
8
|
+
attr_reader :from, :to
|
9
|
+
|
10
|
+
# @param [Array<Object>, NodeContainer, Object] from
|
11
|
+
# @param [Array<Object>, NodeContainer, Object] to
|
12
|
+
def initialize(from, to)
|
13
|
+
@from = to_node_container(from)
|
14
|
+
@to = to_node_container(to)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Disable the map for the given patch context
|
18
|
+
# @return [Boolean]
|
19
|
+
def disable(patch)
|
20
|
+
result = @to.map do |to_node|
|
21
|
+
disabled = @from.map do |from_node|
|
22
|
+
from_node.disable(patch)
|
23
|
+
true
|
24
|
+
end
|
25
|
+
disabled.any?
|
26
|
+
end
|
27
|
+
result.any?
|
28
|
+
end
|
29
|
+
|
30
|
+
# Enable this map for the given nodes
|
31
|
+
# @param [::Patch::Patch] patch The patch context to enable the map in
|
32
|
+
# @return [Boolean] Whether nodes were enabled
|
33
|
+
def enable(patch)
|
34
|
+
result = @to.map do |to_node|
|
35
|
+
enabled = @from.map do |from_node|
|
36
|
+
from_node.listen(patch) do |messages|
|
37
|
+
to_node.puts(patch, messages)
|
38
|
+
end
|
39
|
+
true
|
40
|
+
end
|
41
|
+
enabled.any?
|
42
|
+
end
|
43
|
+
result.flatten.any?
|
44
|
+
end
|
45
|
+
|
46
|
+
# The nodes for this map, collected
|
47
|
+
# @return [NodeContainer]
|
48
|
+
def nodes
|
49
|
+
@from | @to
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
# Convert the given arg to a node container
|
55
|
+
# @param [Object] object
|
56
|
+
# @return [NodeContainer]
|
57
|
+
def to_node_container(object)
|
58
|
+
if !object.kind_of?(Array) || !object.kind_of?(Node::Container)
|
59
|
+
object = [object].flatten.compact
|
60
|
+
end
|
61
|
+
if object.kind_of?(Array)
|
62
|
+
object = Node::Container.new(object)
|
63
|
+
end
|
64
|
+
object
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
data/lib/patch/node.rb
ADDED
data/lib/patch/patch.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
module Patch
|
2
|
+
|
3
|
+
# A single patch consisting of a node mapping and actions
|
4
|
+
class Patch
|
5
|
+
|
6
|
+
attr_reader :actions, :maps, :name
|
7
|
+
|
8
|
+
# @param [Symbol, String] name
|
9
|
+
# @param [Array<Node::Map>, Node::Map] maps A node map or maps
|
10
|
+
# @param [Array<Hash>, Hash] actions An action or actions
|
11
|
+
def initialize(name, maps, actions)
|
12
|
+
@name = name
|
13
|
+
populate(maps, actions)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Enable the given nodes to implement this patch
|
17
|
+
# @param [Node::Container] nodes
|
18
|
+
# @return [Boolean]
|
19
|
+
def enable
|
20
|
+
result = @maps.map { |map| map.enable(self) }
|
21
|
+
result.any?
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# Populate the patch
|
27
|
+
# @param [Array<Hash, Node::Map>, Hash, Node::Map] maps
|
28
|
+
# @param [Array<Hash>, Hash] actions
|
29
|
+
# @return [Patch]
|
30
|
+
def populate(maps, actions)
|
31
|
+
populate_maps(maps)
|
32
|
+
populate_actions(actions)
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
# Populate the patch actions from various arg formats
|
37
|
+
# @param [Array<Hash>, Hash] actions
|
38
|
+
# @return [Array<Hash>]
|
39
|
+
def populate_actions(actions)
|
40
|
+
@actions = actions.kind_of?(Hash) ? [actions] : actions
|
41
|
+
end
|
42
|
+
|
43
|
+
# Populate the node maps from various arg formats
|
44
|
+
# @param [Array<Hash, Node::Map>, Hash, Node::Map] maps
|
45
|
+
# @return [Array<Node::Map>]
|
46
|
+
def populate_maps(maps)
|
47
|
+
maps = [maps] unless maps.kind_of?(Array)
|
48
|
+
maps = maps.map do |map|
|
49
|
+
if map.kind_of?(Hash)
|
50
|
+
Node::Map.new(map.keys.first, map.values.first)
|
51
|
+
else
|
52
|
+
map
|
53
|
+
end
|
54
|
+
end
|
55
|
+
@maps = maps.flatten.compact
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|