fathom 0.3.7 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. data/.autotest +7 -5
  2. data/.document +2 -2
  3. data/Gemfile +9 -10
  4. data/{LICENSE → LICENSE.txt} +1 -1
  5. data/README.md +29 -90
  6. data/Rakefile +34 -32
  7. data/VERSION +1 -1
  8. data/fathom.gemspec +105 -0
  9. data/features/fathom.feature +26 -0
  10. data/features/step_definitions/fathom_steps.rb +23 -0
  11. data/features/support/env.rb +13 -0
  12. data/lib/ext/array.rb +6 -2
  13. data/lib/ext/string.rb +86 -7
  14. data/lib/fathom.rb +51 -88
  15. data/lib/fathom/behaviors/attribute_system.rb +91 -0
  16. data/lib/fathom/behaviors/context_behavior.rb +28 -0
  17. data/lib/fathom/behaviors/plugins.rb +16 -0
  18. data/lib/fathom/contexts/network_population.rb +47 -0
  19. data/lib/fathom/contexts/network_traversal.rb +4 -0
  20. data/lib/fathom/data/adjacency_matrix.rb +27 -0
  21. data/lib/fathom/data/definition.rb +22 -0
  22. data/lib/fathom/data/edge.rb +58 -0
  23. data/lib/fathom/data/network.rb +35 -0
  24. data/lib/fathom/data/outcome.rb +30 -0
  25. data/lib/fathom/data/property.rb +31 -0
  26. data/lib/fathom/data/variable.rb +59 -0
  27. data/lib/fathom/roles/general_graph_tools.rb +87 -0
  28. data/lib/fathom/roles/network_builder.rb +61 -0
  29. data/spec/fathom/behaviors/attribute_system_spec.rb +141 -0
  30. data/spec/fathom/behaviors/context_behavior_spec.rb +15 -0
  31. data/spec/fathom/behaviors/plugins_spec.rb +80 -0
  32. data/spec/fathom/contexts/network_population_spec.rb +55 -0
  33. data/spec/fathom/contexts/network_traversal_spec.rb +11 -0
  34. data/spec/fathom/data/adjacency_matrix_spec.rb +42 -0
  35. data/spec/fathom/data/definition_spec.rb +19 -0
  36. data/spec/fathom/data/edge_spec.rb +77 -0
  37. data/spec/fathom/data/network_spec.rb +72 -0
  38. data/spec/fathom/data/outcome_spec.rb +17 -0
  39. data/spec/fathom/data/property_spec.rb +17 -0
  40. data/spec/fathom/data/variable_spec.rb +101 -0
  41. data/spec/fathom/ext/array_spec.rb +17 -0
  42. data/spec/fathom/ext/string_spec.rb +90 -0
  43. data/spec/fathom/roles/general_graph_tools_spec.rb +95 -0
  44. data/spec/fathom/roles/network_builder_spec.rb +90 -0
  45. data/spec/fathom_spec.rb +28 -49
  46. data/spec/spec_helper.rb +7 -11
  47. data/spec/support/context_behavior.rb +14 -0
  48. data/spec/support/custom_matchers.rb +12 -0
  49. data/spec/support/files.rb +8 -0
  50. data/spec/support/network.yml +42 -0
  51. metadata +133 -174
  52. data/.bundle/config +0 -2
  53. data/.gitignore +0 -6
  54. data/Gemfile.lock +0 -42
  55. data/TODO.md +0 -127
  56. data/autotest/discover.rb +0 -1
  57. data/lib/ext/faster_csv.rb +0 -1
  58. data/lib/ext/open_struct.rb +0 -17
  59. data/lib/fathom/agent.rb +0 -48
  60. data/lib/fathom/agent/agent_cluster.rb +0 -23
  61. data/lib/fathom/agent/properties.rb +0 -48
  62. data/lib/fathom/archive/causal_graph.rb +0 -12
  63. data/lib/fathom/archive/concept.rb +0 -83
  64. data/lib/fathom/archive/conditional_probability_matrix.rb +0 -119
  65. data/lib/fathom/archive/inverter.rb +0 -20
  66. data/lib/fathom/archive/n2.rb +0 -198
  67. data/lib/fathom/archive/n3.rb +0 -119
  68. data/lib/fathom/archive/node.rb +0 -97
  69. data/lib/fathom/archive/noodle.rb +0 -136
  70. data/lib/fathom/archive/scratch.rb +0 -45
  71. data/lib/fathom/distributions.rb +0 -8
  72. data/lib/fathom/distributions/discrete_gaussian.rb +0 -44
  73. data/lib/fathom/distributions/discrete_uniform.rb +0 -25
  74. data/lib/fathom/distributions/gaussian.rb +0 -46
  75. data/lib/fathom/distributions/uniform.rb +0 -35
  76. data/lib/fathom/import.rb +0 -85
  77. data/lib/fathom/import/csv_import.rb +0 -59
  78. data/lib/fathom/import/import_node.rb +0 -17
  79. data/lib/fathom/import/yaml_import.rb +0 -74
  80. data/lib/fathom/knowledge_base.rb +0 -46
  81. data/lib/fathom/knowledge_base/search.rb +0 -19
  82. data/lib/fathom/monte_carlo_set.rb +0 -152
  83. data/lib/fathom/node.rb +0 -139
  84. data/lib/fathom/node/belief_node.rb +0 -121
  85. data/lib/fathom/node/cpm_node.rb +0 -100
  86. data/lib/fathom/node/data_collection.rb +0 -97
  87. data/lib/fathom/node/data_node.rb +0 -22
  88. data/lib/fathom/node/decision.rb +0 -11
  89. data/lib/fathom/node/discrete_node.rb +0 -41
  90. data/lib/fathom/node/fact.rb +0 -24
  91. data/lib/fathom/node/mc_node.rb +0 -70
  92. data/lib/fathom/node/node_extensions/enforced_name.rb +0 -12
  93. data/lib/fathom/node/node_extensions/numeric_methods.rb +0 -68
  94. data/lib/fathom/node/plausible_range.rb +0 -98
  95. data/lib/fathom/simulation.rb +0 -59
  96. data/lib/fathom/simulation/tick_methods.rb +0 -25
  97. data/lib/fathom/simulation/tick_simulation.rb +0 -12
  98. data/lib/fathom/value_description.rb +0 -79
  99. data/lib/options_hash.rb +0 -186
  100. data/spec/ext/array_spec.rb +0 -10
  101. data/spec/ext/faster_csv_spec.rb +0 -10
  102. data/spec/ext/open_struct_spec.rb +0 -20
  103. data/spec/ext/string_spec.rb +0 -7
  104. data/spec/fathom/agent/agent_cluster_spec.rb +0 -17
  105. data/spec/fathom/agent_spec.rb +0 -51
  106. data/spec/fathom/distributions/discrete_gaussian_spec.rb +0 -64
  107. data/spec/fathom/distributions/discrete_uniform_spec.rb +0 -0
  108. data/spec/fathom/distributions/gaussian_spec.rb +0 -64
  109. data/spec/fathom/distributions/uniform_spec.rb +0 -0
  110. data/spec/fathom/import/csv_import_spec.rb +0 -52
  111. data/spec/fathom/import/import_node_spec.rb +0 -10
  112. data/spec/fathom/import/yaml_import_spec.rb +0 -73
  113. data/spec/fathom/import_spec.rb +0 -36
  114. data/spec/fathom/knowledge_base_spec.rb +0 -20
  115. data/spec/fathom/monte_carlo_set_spec.rb +0 -149
  116. data/spec/fathom/node/belief_node_spec.rb +0 -180
  117. data/spec/fathom/node/cpm_node_spec.rb +0 -144
  118. data/spec/fathom/node/data_collection_spec.rb +0 -26
  119. data/spec/fathom/node/data_node_spec.rb +0 -102
  120. data/spec/fathom/node/decision_spec.rb +0 -15
  121. data/spec/fathom/node/discrete_node_spec.rb +0 -56
  122. data/spec/fathom/node/fact_spec.rb +0 -33
  123. data/spec/fathom/node/mc_node_spec.rb +0 -66
  124. data/spec/fathom/node/node_extensions/enforced_name_spec.rb +0 -15
  125. data/spec/fathom/node/node_extensions/numeric_methods_spec.rb +0 -124
  126. data/spec/fathom/node/plausible_range_spec.rb +0 -151
  127. data/spec/fathom/node_spec.rb +0 -172
  128. data/spec/fathom/simulation/tick_simulation_spec.rb +0 -32
  129. data/spec/fathom/simulation_spec.rb +0 -24
  130. data/spec/fathom/value_description_spec.rb +0 -70
  131. data/spec/support/demo.yml +0 -17
  132. data/spec/support/demo_agent.rb +0 -8
  133. data/spec/support/dummy_numeric_node.rb +0 -8
  134. data/spec/support/fact.yml +0 -11
@@ -0,0 +1,13 @@
1
+ require 'bundler'
2
+ begin
3
+ Bundler.setup(:default, :development)
4
+ rescue Bundler::BundlerError => e
5
+ $stderr.puts e.message
6
+ $stderr.puts "Run `bundle install` to install missing gems"
7
+ exit e.status_code
8
+ end
9
+
10
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
11
+ require 'fathom'
12
+
13
+ require 'rspec/expectations'
@@ -1,5 +1,9 @@
1
1
  class Array
2
- def rand
3
- self[Kernel.rand(self.length)]
2
+ def invert(&block)
3
+ h = {}
4
+ self.each_with_index do |x, i|
5
+ h[x] = block ? yield(x, i) : i
6
+ end
7
+ h
4
8
  end
5
9
  end
@@ -1,8 +1,39 @@
1
- # From ActiveSupport
2
- class String
1
+ module Inflector
2
+ extend self
3
+
4
+ def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
5
+ if first_letter_in_uppercase
6
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
7
+ else
8
+ lower_case_and_underscored_word.to_s[0].chr.downcase + camelize(lower_case_and_underscored_word)[1..-1]
9
+ end
10
+ end
11
+
12
+ def underscore(camel_cased_word)
13
+ word = camel_cased_word.to_s.dup
14
+ word.gsub!(/::/, '/')
15
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
16
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
17
+ word.tr!("-", "_")
18
+ word.downcase!
19
+ word
20
+ end
21
+
22
+ def dasherize(underscored_word)
23
+ underscored_word.gsub(/_/, '-')
24
+ end
25
+
26
+ def demodulize(class_name_in_module)
27
+ class_name_in_module.to_s.gsub(/^.*::/, '')
28
+ end
29
+
30
+ def foreign_key(class_name, separate_class_name_and_id_with_underscore = true)
31
+ underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id")
32
+ end
33
+
3
34
  if Module.method(:const_get).arity == 1
4
- def constantize
5
- names = self.split('::')
35
+ def constantize(camel_cased_word)
36
+ names = camel_cased_word.split('::')
6
37
  names.shift if names.empty? || names.first.empty?
7
38
 
8
39
  constant = Object
@@ -12,8 +43,8 @@ class String
12
43
  constant
13
44
  end
14
45
  else
15
- def constantize #:nodoc:
16
- names = self.split('::')
46
+ def constantize(camel_cased_word) #:nodoc:
47
+ names = camel_cased_word.split('::')
17
48
  names.shift if names.empty? || names.first.empty?
18
49
 
19
50
  constant = Object
@@ -23,5 +54,53 @@ class String
23
54
  constant
24
55
  end
25
56
  end
57
+
58
+ def ordinalize(number)
59
+ if (11..13).include?(number.to_i % 100)
60
+ "#{number}th"
61
+ else
62
+ case number.to_i % 10
63
+ when 1; "#{number}st"
64
+ when 2; "#{number}nd"
65
+ when 3; "#{number}rd"
66
+ else "#{number}th"
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ class String
73
+ def constantize
74
+ Inflector.constantize(self)
75
+ end
76
+
77
+ def camelize(first_letter_in_uppercase = true)
78
+ Inflector.camelize(self, first_letter_in_uppercase)
79
+ end
80
+
81
+ def underscore
82
+ Inflector.underscore(self)
83
+ end
84
+
85
+ def dasherize
86
+ Inflector.dasherize(self)
87
+ end
88
+
89
+ def demodulize
90
+ Inflector.demodulize(self)
91
+ end
92
+
93
+ def foreign_key(separate_class_name_and_id_with_underscore = true)
94
+ Inflector.foreign_key(self, separate_class_name_and_id_with_underscore)
95
+ end
96
+
97
+ def ordinalize
98
+ Inflector.ordinalize(self)
99
+ end
100
+
101
+ def wrap(col=80)
102
+ # http://blog.macromates.com/2006/wrapping-text-with-regular-expressions/
103
+ gsub(/(.{1,#{col}})( +|$\n?)|(.{1,#{col}})/, "\\1\\3\n")
104
+ end
26
105
 
27
- end
106
+ end
@@ -1,103 +1,66 @@
1
1
  # ================
2
2
  # = Dependencies =
3
3
  # ================
4
+ Dir.glob("#{File.dirname(__FILE__)}/ext/*.rb").each { |file| require file}
4
5
 
5
- # Make decoupling easier with an informed LoadPath
6
- $:.unshift(File.dirname(__FILE__))
7
- $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), 'fathom')))
8
-
9
- require 'rubygems'
10
-
11
- require "gsl"
12
- require 'options_hash'
13
-
14
- require 'ext/open_struct'
15
- require 'ext/array'
16
- require 'ext/string'
6
+ require 'uuid'
17
7
 
18
8
  module Fathom
19
- lib = File.expand_path(File.dirname(__FILE__))
20
- $LOAD_PATH.unshift(lib)
21
9
 
22
- # Autoload classes and modules so that we only load as much of the library as we're using.
23
- # This allows us to have a fairly large library without taking up a lot of memory unless we need it.
24
- # autoload :Node, "node"
25
- # autoload :BeliefNode, "node/belief_node"
26
- # autoload :DataCollection, "node/data_collection"
27
- # autoload :DataNode, "node/data_node"
28
- # autoload :DiscreteNode, "node/discrete_node"
29
- # autoload :MCNode, "node/mc_node"
30
- # autoload :PlausibleRange, "node/plausible_range"
31
- # autoload :Fact, "node/fact"
32
- # autoload :Decision, "node/decision"
33
- # autoload :CPMNode, 'node/cpm_node'
34
- #
35
- # autoload :ValueDescription, "value_description"
36
- # autoload :MonteCarloSet, "monte_carlo_set"
37
- # autoload :KnowledgeBase, "knowledge_base"
38
- #
39
- # autoload :Import, "import"
40
- # autoload :ImportNode, "import/import_node"
41
- # autoload :YAMLImport, 'import/yaml_import'
42
- # autoload :CSVImport, 'import/csv_import'
43
- # # autoload :RDFImport, 'import/rdf_import'
44
- # # autoload :SQLiteImport, 'import/sqlite_import'
45
- #
46
- # autoload :Simulation, 'simulation'
47
- # autoload :TickMethods, 'simulation/tick_methods'
48
- # autoload :TickSimulation, 'simulation/tick_simulation'
49
- #
50
- # autoload :Agent, 'agent'
51
- # autoload :Properties, 'agent/properties'
52
- # autoload :AgentCluster, 'agent/agent_cluster'
53
- #
54
- # autoload :EnforcedName, 'node/node_extensions/enforced_name'
55
- # autoload :NumericMethods, 'node/node_extensions/numeric_methods'
56
-
57
- require 'distributions'
58
- module Distributions
59
- autoload :Gaussian, 'distributions/gaussian'
60
- autoload :Uniform, 'distributions/uniform'
61
- autoload :DiscreteGaussian, 'distributions/discrete_gaussian'
62
- autoload :DiscreteUniform, 'distributions/discrete_uniform'
10
+ class Config
11
+ attr_writer :storage
12
+ def storage
13
+ @storage ||= Hash
14
+ end
63
15
  end
64
-
65
- def knowledge_base
66
- @knowledge_base ||= KnowledgeBase.new
16
+
17
+ # =================
18
+ # = Configuration =
19
+ # =================
20
+ class << self
21
+ # A reset-able configuration that provides access to other services (pod storage, say)
22
+ def config
23
+ @config ||= Config.new
24
+ end
25
+
26
+ # The reset on the configuration
27
+ def reset_config!
28
+ @config = Config.new
29
+ end
67
30
  end
68
- alias :kb :knowledge_base
31
+
69
32
  end
70
33
 
71
- # Temporary
72
- # include Fathom
73
-
74
- Fathom.autoload :Node, "node"
75
- Fathom.autoload :BeliefNode, "node/belief_node"
76
- Fathom.autoload :DataCollection, "node/data_collection"
77
- Fathom.autoload :DataNode, "node/data_node"
78
- Fathom.autoload :DiscreteNode, "node/discrete_node"
79
- Fathom.autoload :MCNode, "node/mc_node"
80
- Fathom.autoload :PlausibleRange, "node/plausible_range"
81
- Fathom.autoload :Fact, "node/fact"
82
- Fathom.autoload :Decision, "node/decision"
83
- Fathom.autoload :CPMNode, 'node/cpm_node'
84
-
85
- Fathom.autoload :ValueDescription, "value_description"
86
- Fathom.autoload :MonteCarloSet, "monte_carlo_set"
87
- Fathom.autoload :KnowledgeBase, "knowledge_base"
34
+ def path(path)
35
+ File.expand_path("../fathom/#{path}", __FILE__)
36
+ end
88
37
 
89
- Fathom.autoload :Import, "import"
90
- Fathom.autoload :ImportNode, "import/import_node"
91
- Fathom.autoload :YAMLImport, 'import/yaml_import'
92
- Fathom.autoload :CSVImport, 'import/csv_import'
38
+ # =============
39
+ # = Behaviors =
40
+ # =============
41
+ Fathom.autoload :AttributeSystem, path('behaviors/attribute_system')
42
+ Fathom.autoload :ContextBehavior, path('behaviors/context_behavior')
43
+ Fathom.autoload :Plugins, path('behaviors/plugins')
93
44
 
94
- Fathom.autoload :Simulation, 'simulation'
95
- Fathom.autoload :TickMethods, 'simulation/tick_methods'
96
- Fathom.autoload :TickSimulation, 'simulation/tick_simulation'
45
+ # ===============
46
+ # = Data Models =
47
+ # ===============
48
+ Fathom.autoload :AdjacencyMatrix, path('data/adjacency_matrix')
49
+ Fathom.autoload :Definition, path('data/definition')
50
+ Fathom.autoload :Edge, path('data/edge')
51
+ Fathom.autoload :Network, path('data/network')
52
+ Fathom.autoload :Outcome, path('data/outcome')
53
+ Fathom.autoload :Property, path('data/property')
54
+ Fathom.autoload :Variable, path('data/variable')
97
55
 
98
- Fathom.autoload :Agent, 'agent'
99
- Fathom.autoload :Properties, 'agent/properties'
100
- Fathom.autoload :AgentCluster, 'agent/agent_cluster'
56
+ # ============
57
+ # = Contexts =
58
+ # ============
59
+ Fathom.autoload :NetworkPopulation, path('contexts/network_population')
60
+ Fathom.autoload :NetworkTraversal, path('contexts/network_traversal')
101
61
 
102
- Fathom.autoload :EnforcedName, 'node/node_extensions/enforced_name'
103
- Fathom.autoload :NumericMethods, 'node/node_extensions/numeric_methods'
62
+ # =========
63
+ # = Roles =
64
+ # =========
65
+ Fathom.autoload :NetworkBuilder, path('roles/network_builder')
66
+ Fathom.autoload :GeneralGraphTools, path('roles/general_graph_tools')
@@ -0,0 +1,91 @@
1
+ module Fathom
2
+
3
+ # This is a simple way to use thin Ruby classes to only store data values for attributes.
4
+ # In this way, we can have data models that can have various roles injected into them at
5
+ # runtime and perform fairly well. We can also have other kinds of data models mixed into
6
+ # Fathom, such as an ActiveRecord or DataMapper model, and we can just ignore this system
7
+ # altogether.
8
+ #
9
+ # It is important that it is easy to set an attributes_proxy. Other Fathom gems
10
+ # (say fm-redis, if I were to write that gem) could override the AttributeSystem default
11
+ # attributes to store data in a Redis data store directly. This is what the set_attributes_proxy
12
+ # is designed to do here.
13
+ #
14
+ # Example Usage:
15
+ # require 'memcache'
16
+ # CACHE = MemCache.new 'localhost:11211', :namespace => 'my_project'
17
+ # CACHE[1] = {:name => 'special'}
18
+ #
19
+ # class MyClass
20
+ # extend Fathom::Plugins
21
+ # plugin Fathom::AttributeSystem
22
+ #
23
+ # attribute :name
24
+ # attribute :value, 1
25
+ #
26
+ # def initialize(attrs={})
27
+ # @attributes = attrs
28
+ # end
29
+ # end
30
+ #
31
+ # obj = MyClass.new(CACHE[1])
32
+ # obj.name # => special
33
+ # obj.value # => 1
34
+ module AttributeSystem
35
+
36
+ module ClassMethods
37
+
38
+ # Define an attribute, or property of this class.
39
+ # Useful for very thin, generic Ruby classes for Data models.
40
+ def attribute(getter_name, default=nil)
41
+
42
+ # Define a getter on the object
43
+ define_method(getter_name) do
44
+
45
+ target = send(self.class.attributes_proxy)
46
+
47
+ return target[getter_name] unless target.respond_to?(:has_key?)
48
+
49
+ if target.has_key?(getter_name)
50
+ target[getter_name]
51
+ else
52
+ self.class.attribute_defaults[getter_name]
53
+ end
54
+ end
55
+
56
+ # Define a setter on the object
57
+ define_method("#{getter_name}=") do |value|
58
+ send(self.class.attributes_proxy)[getter_name] = value
59
+ end
60
+
61
+ # Define a default on the object
62
+ attribute_defaults[getter_name] = default
63
+
64
+ end
65
+
66
+ # Defines where the attributes are stored for the target class.
67
+ def set_attributes_proxy(value)
68
+ @attributes_proxy = value
69
+ end
70
+
71
+ def attributes_proxy
72
+ @attributes_proxy ||= :attributes
73
+ end
74
+
75
+ def attribute_defaults
76
+ @attribute_defaults ||= {}
77
+ end
78
+ end
79
+
80
+ module InstanceMethods
81
+
82
+ # Defines an attributes getter and defaults it to a Hash.
83
+ def attributes
84
+ @attributes ||= {}
85
+ end
86
+
87
+ end
88
+
89
+ end # AttributeSystem
90
+
91
+ end # Fathom
@@ -0,0 +1,28 @@
1
+ module Fathom
2
+ module ContextBehavior
3
+
4
+ module ClassMethods
5
+
6
+ def default_class(value=nil)
7
+ @default_class = value if value
8
+ @default_class
9
+ end
10
+
11
+ def new(*attrs, &block)
12
+ target = attrs.shift
13
+ target ||= default_class.new if default_class
14
+ raise ArgumentError, "You must provide a target object to build this context." unless target
15
+ obj = super(*attrs, &block)
16
+ obj.send(:instance_variable_set, :@object, target)
17
+ obj
18
+ end
19
+ end
20
+
21
+ module InstanceMethods
22
+ attr_reader :object
23
+ end
24
+
25
+ def self.configure(base)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,16 @@
1
+ module Fathom
2
+ module Plugins
3
+ def plugins
4
+ @plugins ||= []
5
+ end
6
+
7
+ def plugin(mod)
8
+ include mod unless mod.const_defined?(:InstanceMethods)
9
+ extend mod::ClassMethods if mod.const_defined?(:ClassMethods)
10
+ include mod::InstanceMethods if mod.const_defined?(:InstanceMethods)
11
+ mod.configure(self) if mod.respond_to?(:configure)
12
+ plugins << mod
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,47 @@
1
+ module Fathom
2
+ class NetworkPopulation
3
+ # ============
4
+ # = Behavior =
5
+ # ============
6
+ extend Plugins
7
+ plugin ContextBehavior
8
+ default_class Network
9
+
10
+ # Uses YAML to populate a network.
11
+ # Expects a format in the YAML that mirrors the data models we are using.
12
+ #
13
+ # Dependencies:
14
+ # * yaml (standard library)
15
+ # * open-uri (standard library)
16
+ #
17
+ # Roles: NetworkBuilder
18
+ #
19
+ # Usage:
20
+ # @context = NetworkPopulation.new(some_network)
21
+ # @context.import_records_from_yaml(:filename => 'some_network.yml')
22
+ def import_records_from_yaml(opts={})
23
+ require 'yaml'
24
+ require 'open-uri'
25
+ object.extend NetworkBuilder
26
+ hash = extract_data_hash_from_parameters(opts)
27
+ object.from_hash(hash)
28
+ end
29
+
30
+ protected
31
+
32
+ # Contract: return a hash, the best one you can find, or an empty one.
33
+ def extract_data_hash_from_parameters(opts)
34
+ if opts[:filename]
35
+ data_from_yaml_file(opts[:filename])
36
+ else
37
+ {}
38
+ end
39
+ end
40
+
41
+ # Contract: return a hash or raise an error
42
+ def data_from_yaml_file(filename)
43
+ YAML.load_file(filename)
44
+ end
45
+
46
+ end
47
+ end