openstudio-workflow 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +72 -72
- data/README.md +48 -48
- data/Rakefile +36 -36
- data/lib/openstudio/workflow/adapters/input/local.rb +240 -240
- data/lib/openstudio/workflow/adapters/output/local.rb +95 -95
- data/lib/openstudio/workflow/adapters/output/socket.rb +91 -91
- data/lib/openstudio/workflow/adapters/output/web.rb +66 -66
- data/lib/openstudio/workflow/adapters/output_adapter.rb +147 -147
- data/lib/openstudio/workflow/job.rb +22 -22
- data/lib/openstudio/workflow/jobs/resources/monthly_report.idf +222 -222
- data/lib/openstudio/workflow/jobs/run_energyplus.rb +49 -49
- data/lib/openstudio/workflow/jobs/run_ep_measures.rb +55 -55
- data/lib/openstudio/workflow/jobs/run_initialization.rb +167 -167
- data/lib/openstudio/workflow/jobs/run_os_measures.rb +69 -69
- data/lib/openstudio/workflow/jobs/run_postprocess.rb +53 -53
- data/lib/openstudio/workflow/jobs/run_preprocess.rb +69 -69
- data/lib/openstudio/workflow/jobs/run_reporting_measures.rb +98 -98
- data/lib/openstudio/workflow/jobs/run_translation.rb +61 -61
- data/lib/openstudio/workflow/multi_delegator.rb +46 -46
- data/lib/openstudio/workflow/registry.rb +137 -137
- data/lib/openstudio/workflow/run.rb +299 -299
- data/lib/openstudio/workflow/time_logger.rb +53 -53
- data/lib/openstudio/workflow/util/energyplus.rb +564 -564
- data/lib/openstudio/workflow/util/io.rb +33 -33
- data/lib/openstudio/workflow/util/measure.rb +588 -586
- data/lib/openstudio/workflow/util/model.rb +100 -100
- data/lib/openstudio/workflow/util/post_process.rb +187 -187
- data/lib/openstudio/workflow/util/weather_file.rb +108 -108
- data/lib/openstudio/workflow/util.rb +14 -14
- data/lib/openstudio/workflow/version.rb +24 -24
- data/lib/openstudio/workflow_json.rb +426 -426
- data/lib/openstudio/workflow_runner.rb +215 -215
- data/lib/openstudio-workflow.rb +49 -49
- metadata +3 -3
@@ -1,61 +1,61 @@
|
|
1
|
-
######################################################################
|
2
|
-
# Copyright (c) 2008-2014, Alliance for Sustainable Energy.
|
3
|
-
# All rights reserved.
|
4
|
-
#
|
5
|
-
# This library is free software; you can redistribute it and/or
|
6
|
-
# modify it under the terms of the GNU Lesser General Public
|
7
|
-
# License as published by the Free Software Foundation; either
|
8
|
-
# version 2.1 of the License, or (at your option) any later version.
|
9
|
-
#
|
10
|
-
# This library is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
-
# Lesser General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU Lesser General Public
|
16
|
-
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
-
######################################################################
|
19
|
-
|
20
|
-
# Run the initialization job to validate the directory and initialize the adapters.
|
21
|
-
class RunTranslation < OpenStudio::Workflow::Job
|
22
|
-
require 'openstudio/workflow/util/model'
|
23
|
-
include OpenStudio::Workflow::Util::Model
|
24
|
-
|
25
|
-
def initialize(input_adapter, output_adapter, registry, options = {})
|
26
|
-
super
|
27
|
-
end
|
28
|
-
|
29
|
-
def perform
|
30
|
-
@logger.debug "Calling #{__method__} in the #{self.class} class"
|
31
|
-
|
32
|
-
# Ensure that the run directory is created
|
33
|
-
FileUtils.mkdir_p(@registry[:run_dir])
|
34
|
-
|
35
|
-
# Copy in the weather file defined in the registry, or alternately in the options
|
36
|
-
if @registry[:wf]
|
37
|
-
@logger.info "Weather file for EnergyPlus simulation is #{@registry[:wf]}"
|
38
|
-
FileUtils.copy(@registry[:wf], "#{@registry[:run_dir]}/in.epw")
|
39
|
-
@registry.register(:wf) { "#{@registry[:run_dir]}/in.epw" }
|
40
|
-
else
|
41
|
-
@logger.warn "EPW file not found or not sent to #{self.class}"
|
42
|
-
end
|
43
|
-
|
44
|
-
# Translate the OSM to an IDF
|
45
|
-
@logger.info 'Beginning the translation to IDF'
|
46
|
-
@registry[:time_logger].start('Translating to EnergyPlus') if @registry[:time_logger]
|
47
|
-
model_idf = translate_to_energyplus @registry[:model], @logger
|
48
|
-
@registry[:time_logger].stop('Translating to EnergyPlus') if @registry[:time_logger]
|
49
|
-
@registry.register(:model_idf) { model_idf }
|
50
|
-
@logger.info 'Successfully translated to IDF'
|
51
|
-
|
52
|
-
# Save the generated IDF file if the :debug option is true
|
53
|
-
return nil unless @options[:debug]
|
54
|
-
@registry[:time_logger].start('Saving IDF') if @registry[:time_logger]
|
55
|
-
idf_name = save_idf(@registry[:model_idf], @registry[:root_dir])
|
56
|
-
@registry[:time_logger].stop('Saving IDF') if @registry[:time_logger]
|
57
|
-
@logger.debug "Saved IDF as #{idf_name}"
|
58
|
-
|
59
|
-
nil
|
60
|
-
end
|
61
|
-
end
|
1
|
+
######################################################################
|
2
|
+
# Copyright (c) 2008-2014, Alliance for Sustainable Energy.
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License as published by the Free Software Foundation; either
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
# Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
16
|
+
# License along with this library; if not, write to the Free Software
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
+
######################################################################
|
19
|
+
|
20
|
+
# Run the initialization job to validate the directory and initialize the adapters.
|
21
|
+
class RunTranslation < OpenStudio::Workflow::Job
|
22
|
+
require 'openstudio/workflow/util/model'
|
23
|
+
include OpenStudio::Workflow::Util::Model
|
24
|
+
|
25
|
+
def initialize(input_adapter, output_adapter, registry, options = {})
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
def perform
|
30
|
+
@logger.debug "Calling #{__method__} in the #{self.class} class"
|
31
|
+
|
32
|
+
# Ensure that the run directory is created
|
33
|
+
FileUtils.mkdir_p(@registry[:run_dir])
|
34
|
+
|
35
|
+
# Copy in the weather file defined in the registry, or alternately in the options
|
36
|
+
if @registry[:wf]
|
37
|
+
@logger.info "Weather file for EnergyPlus simulation is #{@registry[:wf]}"
|
38
|
+
FileUtils.copy(@registry[:wf], "#{@registry[:run_dir]}/in.epw")
|
39
|
+
@registry.register(:wf) { "#{@registry[:run_dir]}/in.epw" }
|
40
|
+
else
|
41
|
+
@logger.warn "EPW file not found or not sent to #{self.class}"
|
42
|
+
end
|
43
|
+
|
44
|
+
# Translate the OSM to an IDF
|
45
|
+
@logger.info 'Beginning the translation to IDF'
|
46
|
+
@registry[:time_logger].start('Translating to EnergyPlus') if @registry[:time_logger]
|
47
|
+
model_idf = translate_to_energyplus @registry[:model], @logger
|
48
|
+
@registry[:time_logger].stop('Translating to EnergyPlus') if @registry[:time_logger]
|
49
|
+
@registry.register(:model_idf) { model_idf }
|
50
|
+
@logger.info 'Successfully translated to IDF'
|
51
|
+
|
52
|
+
# Save the generated IDF file if the :debug option is true
|
53
|
+
return nil unless @options[:debug]
|
54
|
+
@registry[:time_logger].start('Saving IDF') if @registry[:time_logger]
|
55
|
+
idf_name = save_idf(@registry[:model_idf], @registry[:root_dir])
|
56
|
+
@registry[:time_logger].stop('Saving IDF') if @registry[:time_logger]
|
57
|
+
@logger.debug "Saved IDF as #{idf_name}"
|
58
|
+
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
end
|
@@ -1,46 +1,46 @@
|
|
1
|
-
######################################################################
|
2
|
-
# Copyright (c) 2008-2014, Alliance for Sustainable Energy.
|
3
|
-
# All rights reserved.
|
4
|
-
#
|
5
|
-
# This library is free software; you can redistribute it and/or
|
6
|
-
# modify it under the terms of the GNU Lesser General Public
|
7
|
-
# License as published by the Free Software Foundation; either
|
8
|
-
# version 2.1 of the License, or (at your option) any later version.
|
9
|
-
#
|
10
|
-
# This library is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
-
# Lesser General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU Lesser General Public
|
16
|
-
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
-
######################################################################
|
19
|
-
|
20
|
-
require 'logger'
|
21
|
-
|
22
|
-
class Logger
|
23
|
-
def format_message(severity, datetime, _progname, msg)
|
24
|
-
"[%s %s] %s\n" % [datetime.strftime('%H:%M:%S.%6N'), severity, msg]
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# Class to allow multiple logging paths
|
29
|
-
class MultiDelegator
|
30
|
-
def initialize(*targets)
|
31
|
-
@targets = targets
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.delegate(*methods)
|
35
|
-
methods.each do |m|
|
36
|
-
define_method(m) do |*args|
|
37
|
-
@targets.map { |t| t.send(m, *args) }
|
38
|
-
end
|
39
|
-
end
|
40
|
-
self
|
41
|
-
end
|
42
|
-
|
43
|
-
class <<self
|
44
|
-
alias to new
|
45
|
-
end
|
46
|
-
end
|
1
|
+
######################################################################
|
2
|
+
# Copyright (c) 2008-2014, Alliance for Sustainable Energy.
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License as published by the Free Software Foundation; either
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
# Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
16
|
+
# License along with this library; if not, write to the Free Software
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
+
######################################################################
|
19
|
+
|
20
|
+
require 'logger'
|
21
|
+
|
22
|
+
class Logger
|
23
|
+
def format_message(severity, datetime, _progname, msg)
|
24
|
+
"[%s %s] %s\n" % [datetime.strftime('%H:%M:%S.%6N'), severity, msg]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Class to allow multiple logging paths
|
29
|
+
class MultiDelegator
|
30
|
+
def initialize(*targets)
|
31
|
+
@targets = targets
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.delegate(*methods)
|
35
|
+
methods.each do |m|
|
36
|
+
define_method(m) do |*args|
|
37
|
+
@targets.map { |t| t.send(m, *args) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
class <<self
|
44
|
+
alias to new
|
45
|
+
end
|
46
|
+
end
|
@@ -1,137 +1,137 @@
|
|
1
|
-
module OpenStudio
|
2
|
-
module Workflow
|
3
|
-
# Registers objects in a single place. Based on Hashicorps's Vagrant Registry class
|
4
|
-
#
|
5
|
-
# This allows certain components (such as models, weather files, proxy settings, etc.) to be registered as blocks
|
6
|
-
# and lazily updated. This allows for the state of various objects to be updated through evaluation of or
|
7
|
-
# overwriting the key. An instance of this class is passed between jobs to allow for highly flexible workflow
|
8
|
-
# definitions. Note that hashes can be passed into the registry as follows: hash = {...};
|
9
|
-
# Registry.new.register(:hash) { hash } or Registry.new.register(:hash) { {...} }. This class will likely absorb
|
10
|
-
# un-abstracted elements of the adapter class, see Workflow#Adapter
|
11
|
-
|
12
|
-
# @todo (rhorsey) registry should be a member of WorkflowRunner - DLM
|
13
|
-
# @todo (rhorsey) how is this different than a regular hash? why is it important to be able to register keys with blocks that return values instead of values, looks like the block is called on insert anyway? let's not go crazy on performance optimizations until we have to - DLM
|
14
|
-
class Registry
|
15
|
-
def initialize
|
16
|
-
@items = {}
|
17
|
-
@results_cache = {}
|
18
|
-
end
|
19
|
-
|
20
|
-
# Register a key and cache it's value. Note that if a key with the given name already exists it is overwritten
|
21
|
-
#
|
22
|
-
# @param [] key The key for the passed in block. Symbols are highly recommended
|
23
|
-
# @param [Proc] block The block (Proc) which contains the registered information
|
24
|
-
# @return [] Returns block.call from the registries cache
|
25
|
-
#
|
26
|
-
def register(key, &block)
|
27
|
-
raise ArgumentError, 'block required' unless block_given?
|
28
|
-
@items[key] = block
|
29
|
-
@results_cache[key] = @items[key].call
|
30
|
-
end
|
31
|
-
|
32
|
-
# Get the cached value of the given key
|
33
|
-
#
|
34
|
-
# @param [] key The key defining the block
|
35
|
-
# @return [] Returns the registries cached value for the key or nil if the key was not found
|
36
|
-
#
|
37
|
-
def get(key)
|
38
|
-
return nil unless @items.key?(key)
|
39
|
-
@results_cache[key]
|
40
|
-
end
|
41
|
-
alias [] get
|
42
|
-
|
43
|
-
# Re-evaluate the proc of a key and update the cache
|
44
|
-
#
|
45
|
-
# @param [Sym or String] key This will evaluate the item assigned to the key and update the cache if possible
|
46
|
-
# @return [] If successful the method returns the new value, and if it cannot find or cannot update the key it
|
47
|
-
# returns nil
|
48
|
-
#
|
49
|
-
def eval(key)
|
50
|
-
return nil unless @items.key?(key)
|
51
|
-
begin
|
52
|
-
@items[key].call
|
53
|
-
rescue
|
54
|
-
return nil
|
55
|
-
end
|
56
|
-
@results_cache[key] = @items[key].call
|
57
|
-
end
|
58
|
-
|
59
|
-
# Checks if the given key is registered with the registry
|
60
|
-
#
|
61
|
-
# @return [Boolean]
|
62
|
-
#
|
63
|
-
def key?(key)
|
64
|
-
@items.key?(key)
|
65
|
-
end
|
66
|
-
alias has_key? key?
|
67
|
-
|
68
|
-
# Returns an array populated with the keys of this object
|
69
|
-
#
|
70
|
-
# @return [Array]
|
71
|
-
#
|
72
|
-
def keys
|
73
|
-
@items.keys
|
74
|
-
end
|
75
|
-
|
76
|
-
# Return the number of elements in this registry
|
77
|
-
#
|
78
|
-
# @return [Fixnum]
|
79
|
-
#
|
80
|
-
def length
|
81
|
-
@items.keys.length
|
82
|
-
end
|
83
|
-
alias size length
|
84
|
-
|
85
|
-
# Checks if this registry has any items
|
86
|
-
#
|
87
|
-
# @return [Boolean]
|
88
|
-
#
|
89
|
-
def empty?
|
90
|
-
@items.keys.empty?
|
91
|
-
end
|
92
|
-
|
93
|
-
# Merge one registry with another and return a completely new registry. Note that the result cache is completely
|
94
|
-
# busted, so any gets on the new registry will result in a cache miss
|
95
|
-
#
|
96
|
-
# @param [Registry] other The other #Registry to merge onto of self
|
97
|
-
# @return [Registry] A merged #Registry
|
98
|
-
#
|
99
|
-
def merge(other)
|
100
|
-
self.class.new.tap do |result|
|
101
|
-
result.merge!(self)
|
102
|
-
result.merge!(other)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
# Like #merge but updates self
|
107
|
-
#
|
108
|
-
# @param [Registry] other The other #Registry to merge onto of self
|
109
|
-
# @return [Void]
|
110
|
-
#
|
111
|
-
def merge!(other)
|
112
|
-
@items.merge!(other.__internal_state[:items])
|
113
|
-
self
|
114
|
-
end
|
115
|
-
|
116
|
-
# Converts the registry to a hash
|
117
|
-
#
|
118
|
-
# @return [Hash] The registry as a hash
|
119
|
-
#
|
120
|
-
def to_hash
|
121
|
-
result = {}
|
122
|
-
@results_cache.each_pair do |key, value|
|
123
|
-
result[key] = value
|
124
|
-
end
|
125
|
-
|
126
|
-
result
|
127
|
-
end
|
128
|
-
|
129
|
-
def __internal_state
|
130
|
-
{
|
131
|
-
items: @items,
|
132
|
-
results_cache: @results_cache
|
133
|
-
}
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
1
|
+
module OpenStudio
|
2
|
+
module Workflow
|
3
|
+
# Registers objects in a single place. Based on Hashicorps's Vagrant Registry class
|
4
|
+
#
|
5
|
+
# This allows certain components (such as models, weather files, proxy settings, etc.) to be registered as blocks
|
6
|
+
# and lazily updated. This allows for the state of various objects to be updated through evaluation of or
|
7
|
+
# overwriting the key. An instance of this class is passed between jobs to allow for highly flexible workflow
|
8
|
+
# definitions. Note that hashes can be passed into the registry as follows: hash = {...};
|
9
|
+
# Registry.new.register(:hash) { hash } or Registry.new.register(:hash) { {...} }. This class will likely absorb
|
10
|
+
# un-abstracted elements of the adapter class, see Workflow#Adapter
|
11
|
+
|
12
|
+
# @todo (rhorsey) registry should be a member of WorkflowRunner - DLM
|
13
|
+
# @todo (rhorsey) how is this different than a regular hash? why is it important to be able to register keys with blocks that return values instead of values, looks like the block is called on insert anyway? let's not go crazy on performance optimizations until we have to - DLM
|
14
|
+
class Registry
|
15
|
+
def initialize
|
16
|
+
@items = {}
|
17
|
+
@results_cache = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
# Register a key and cache it's value. Note that if a key with the given name already exists it is overwritten
|
21
|
+
#
|
22
|
+
# @param [] key The key for the passed in block. Symbols are highly recommended
|
23
|
+
# @param [Proc] block The block (Proc) which contains the registered information
|
24
|
+
# @return [] Returns block.call from the registries cache
|
25
|
+
#
|
26
|
+
def register(key, &block)
|
27
|
+
raise ArgumentError, 'block required' unless block_given?
|
28
|
+
@items[key] = block
|
29
|
+
@results_cache[key] = @items[key].call
|
30
|
+
end
|
31
|
+
|
32
|
+
# Get the cached value of the given key
|
33
|
+
#
|
34
|
+
# @param [] key The key defining the block
|
35
|
+
# @return [] Returns the registries cached value for the key or nil if the key was not found
|
36
|
+
#
|
37
|
+
def get(key)
|
38
|
+
return nil unless @items.key?(key)
|
39
|
+
@results_cache[key]
|
40
|
+
end
|
41
|
+
alias [] get
|
42
|
+
|
43
|
+
# Re-evaluate the proc of a key and update the cache
|
44
|
+
#
|
45
|
+
# @param [Sym or String] key This will evaluate the item assigned to the key and update the cache if possible
|
46
|
+
# @return [] If successful the method returns the new value, and if it cannot find or cannot update the key it
|
47
|
+
# returns nil
|
48
|
+
#
|
49
|
+
def eval(key)
|
50
|
+
return nil unless @items.key?(key)
|
51
|
+
begin
|
52
|
+
@items[key].call
|
53
|
+
rescue
|
54
|
+
return nil
|
55
|
+
end
|
56
|
+
@results_cache[key] = @items[key].call
|
57
|
+
end
|
58
|
+
|
59
|
+
# Checks if the given key is registered with the registry
|
60
|
+
#
|
61
|
+
# @return [Boolean]
|
62
|
+
#
|
63
|
+
def key?(key)
|
64
|
+
@items.key?(key)
|
65
|
+
end
|
66
|
+
alias has_key? key?
|
67
|
+
|
68
|
+
# Returns an array populated with the keys of this object
|
69
|
+
#
|
70
|
+
# @return [Array]
|
71
|
+
#
|
72
|
+
def keys
|
73
|
+
@items.keys
|
74
|
+
end
|
75
|
+
|
76
|
+
# Return the number of elements in this registry
|
77
|
+
#
|
78
|
+
# @return [Fixnum]
|
79
|
+
#
|
80
|
+
def length
|
81
|
+
@items.keys.length
|
82
|
+
end
|
83
|
+
alias size length
|
84
|
+
|
85
|
+
# Checks if this registry has any items
|
86
|
+
#
|
87
|
+
# @return [Boolean]
|
88
|
+
#
|
89
|
+
def empty?
|
90
|
+
@items.keys.empty?
|
91
|
+
end
|
92
|
+
|
93
|
+
# Merge one registry with another and return a completely new registry. Note that the result cache is completely
|
94
|
+
# busted, so any gets on the new registry will result in a cache miss
|
95
|
+
#
|
96
|
+
# @param [Registry] other The other #Registry to merge onto of self
|
97
|
+
# @return [Registry] A merged #Registry
|
98
|
+
#
|
99
|
+
def merge(other)
|
100
|
+
self.class.new.tap do |result|
|
101
|
+
result.merge!(self)
|
102
|
+
result.merge!(other)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Like #merge but updates self
|
107
|
+
#
|
108
|
+
# @param [Registry] other The other #Registry to merge onto of self
|
109
|
+
# @return [Void]
|
110
|
+
#
|
111
|
+
def merge!(other)
|
112
|
+
@items.merge!(other.__internal_state[:items])
|
113
|
+
self
|
114
|
+
end
|
115
|
+
|
116
|
+
# Converts the registry to a hash
|
117
|
+
#
|
118
|
+
# @return [Hash] The registry as a hash
|
119
|
+
#
|
120
|
+
def to_hash
|
121
|
+
result = {}
|
122
|
+
@results_cache.each_pair do |key, value|
|
123
|
+
result[key] = value
|
124
|
+
end
|
125
|
+
|
126
|
+
result
|
127
|
+
end
|
128
|
+
|
129
|
+
def __internal_state
|
130
|
+
{
|
131
|
+
items: @items,
|
132
|
+
results_cache: @results_cache
|
133
|
+
}
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|