fathom 0.3.7 → 0.5.0
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.
- data/.autotest +7 -5
- data/.document +2 -2
- data/Gemfile +9 -10
- data/{LICENSE → LICENSE.txt} +1 -1
- data/README.md +29 -90
- data/Rakefile +34 -32
- data/VERSION +1 -1
- data/fathom.gemspec +105 -0
- data/features/fathom.feature +26 -0
- data/features/step_definitions/fathom_steps.rb +23 -0
- data/features/support/env.rb +13 -0
- data/lib/ext/array.rb +6 -2
- data/lib/ext/string.rb +86 -7
- data/lib/fathom.rb +51 -88
- data/lib/fathom/behaviors/attribute_system.rb +91 -0
- data/lib/fathom/behaviors/context_behavior.rb +28 -0
- data/lib/fathom/behaviors/plugins.rb +16 -0
- data/lib/fathom/contexts/network_population.rb +47 -0
- data/lib/fathom/contexts/network_traversal.rb +4 -0
- data/lib/fathom/data/adjacency_matrix.rb +27 -0
- data/lib/fathom/data/definition.rb +22 -0
- data/lib/fathom/data/edge.rb +58 -0
- data/lib/fathom/data/network.rb +35 -0
- data/lib/fathom/data/outcome.rb +30 -0
- data/lib/fathom/data/property.rb +31 -0
- data/lib/fathom/data/variable.rb +59 -0
- data/lib/fathom/roles/general_graph_tools.rb +87 -0
- data/lib/fathom/roles/network_builder.rb +61 -0
- data/spec/fathom/behaviors/attribute_system_spec.rb +141 -0
- data/spec/fathom/behaviors/context_behavior_spec.rb +15 -0
- data/spec/fathom/behaviors/plugins_spec.rb +80 -0
- data/spec/fathom/contexts/network_population_spec.rb +55 -0
- data/spec/fathom/contexts/network_traversal_spec.rb +11 -0
- data/spec/fathom/data/adjacency_matrix_spec.rb +42 -0
- data/spec/fathom/data/definition_spec.rb +19 -0
- data/spec/fathom/data/edge_spec.rb +77 -0
- data/spec/fathom/data/network_spec.rb +72 -0
- data/spec/fathom/data/outcome_spec.rb +17 -0
- data/spec/fathom/data/property_spec.rb +17 -0
- data/spec/fathom/data/variable_spec.rb +101 -0
- data/spec/fathom/ext/array_spec.rb +17 -0
- data/spec/fathom/ext/string_spec.rb +90 -0
- data/spec/fathom/roles/general_graph_tools_spec.rb +95 -0
- data/spec/fathom/roles/network_builder_spec.rb +90 -0
- data/spec/fathom_spec.rb +28 -49
- data/spec/spec_helper.rb +7 -11
- data/spec/support/context_behavior.rb +14 -0
- data/spec/support/custom_matchers.rb +12 -0
- data/spec/support/files.rb +8 -0
- data/spec/support/network.yml +42 -0
- metadata +133 -174
- data/.bundle/config +0 -2
- data/.gitignore +0 -6
- data/Gemfile.lock +0 -42
- data/TODO.md +0 -127
- data/autotest/discover.rb +0 -1
- data/lib/ext/faster_csv.rb +0 -1
- data/lib/ext/open_struct.rb +0 -17
- data/lib/fathom/agent.rb +0 -48
- data/lib/fathom/agent/agent_cluster.rb +0 -23
- data/lib/fathom/agent/properties.rb +0 -48
- data/lib/fathom/archive/causal_graph.rb +0 -12
- data/lib/fathom/archive/concept.rb +0 -83
- data/lib/fathom/archive/conditional_probability_matrix.rb +0 -119
- data/lib/fathom/archive/inverter.rb +0 -20
- data/lib/fathom/archive/n2.rb +0 -198
- data/lib/fathom/archive/n3.rb +0 -119
- data/lib/fathom/archive/node.rb +0 -97
- data/lib/fathom/archive/noodle.rb +0 -136
- data/lib/fathom/archive/scratch.rb +0 -45
- data/lib/fathom/distributions.rb +0 -8
- data/lib/fathom/distributions/discrete_gaussian.rb +0 -44
- data/lib/fathom/distributions/discrete_uniform.rb +0 -25
- data/lib/fathom/distributions/gaussian.rb +0 -46
- data/lib/fathom/distributions/uniform.rb +0 -35
- data/lib/fathom/import.rb +0 -85
- data/lib/fathom/import/csv_import.rb +0 -59
- data/lib/fathom/import/import_node.rb +0 -17
- data/lib/fathom/import/yaml_import.rb +0 -74
- data/lib/fathom/knowledge_base.rb +0 -46
- data/lib/fathom/knowledge_base/search.rb +0 -19
- data/lib/fathom/monte_carlo_set.rb +0 -152
- data/lib/fathom/node.rb +0 -139
- data/lib/fathom/node/belief_node.rb +0 -121
- data/lib/fathom/node/cpm_node.rb +0 -100
- data/lib/fathom/node/data_collection.rb +0 -97
- data/lib/fathom/node/data_node.rb +0 -22
- data/lib/fathom/node/decision.rb +0 -11
- data/lib/fathom/node/discrete_node.rb +0 -41
- data/lib/fathom/node/fact.rb +0 -24
- data/lib/fathom/node/mc_node.rb +0 -70
- data/lib/fathom/node/node_extensions/enforced_name.rb +0 -12
- data/lib/fathom/node/node_extensions/numeric_methods.rb +0 -68
- data/lib/fathom/node/plausible_range.rb +0 -98
- data/lib/fathom/simulation.rb +0 -59
- data/lib/fathom/simulation/tick_methods.rb +0 -25
- data/lib/fathom/simulation/tick_simulation.rb +0 -12
- data/lib/fathom/value_description.rb +0 -79
- data/lib/options_hash.rb +0 -186
- data/spec/ext/array_spec.rb +0 -10
- data/spec/ext/faster_csv_spec.rb +0 -10
- data/spec/ext/open_struct_spec.rb +0 -20
- data/spec/ext/string_spec.rb +0 -7
- data/spec/fathom/agent/agent_cluster_spec.rb +0 -17
- data/spec/fathom/agent_spec.rb +0 -51
- data/spec/fathom/distributions/discrete_gaussian_spec.rb +0 -64
- data/spec/fathom/distributions/discrete_uniform_spec.rb +0 -0
- data/spec/fathom/distributions/gaussian_spec.rb +0 -64
- data/spec/fathom/distributions/uniform_spec.rb +0 -0
- data/spec/fathom/import/csv_import_spec.rb +0 -52
- data/spec/fathom/import/import_node_spec.rb +0 -10
- data/spec/fathom/import/yaml_import_spec.rb +0 -73
- data/spec/fathom/import_spec.rb +0 -36
- data/spec/fathom/knowledge_base_spec.rb +0 -20
- data/spec/fathom/monte_carlo_set_spec.rb +0 -149
- data/spec/fathom/node/belief_node_spec.rb +0 -180
- data/spec/fathom/node/cpm_node_spec.rb +0 -144
- data/spec/fathom/node/data_collection_spec.rb +0 -26
- data/spec/fathom/node/data_node_spec.rb +0 -102
- data/spec/fathom/node/decision_spec.rb +0 -15
- data/spec/fathom/node/discrete_node_spec.rb +0 -56
- data/spec/fathom/node/fact_spec.rb +0 -33
- data/spec/fathom/node/mc_node_spec.rb +0 -66
- data/spec/fathom/node/node_extensions/enforced_name_spec.rb +0 -15
- data/spec/fathom/node/node_extensions/numeric_methods_spec.rb +0 -124
- data/spec/fathom/node/plausible_range_spec.rb +0 -151
- data/spec/fathom/node_spec.rb +0 -172
- data/spec/fathom/simulation/tick_simulation_spec.rb +0 -32
- data/spec/fathom/simulation_spec.rb +0 -24
- data/spec/fathom/value_description_spec.rb +0 -70
- data/spec/support/demo.yml +0 -17
- data/spec/support/demo_agent.rb +0 -8
- data/spec/support/dummy_numeric_node.rb +0 -8
- 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'
|
data/lib/ext/array.rb
CHANGED
data/lib/ext/string.rb
CHANGED
|
@@ -1,8 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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 =
|
|
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 =
|
|
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
|
data/lib/fathom.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
66
|
-
|
|
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
|
-
|
|
31
|
+
|
|
69
32
|
end
|
|
70
33
|
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
Fathom.autoload :
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
56
|
+
# ============
|
|
57
|
+
# = Contexts =
|
|
58
|
+
# ============
|
|
59
|
+
Fathom.autoload :NetworkPopulation, path('contexts/network_population')
|
|
60
|
+
Fathom.autoload :NetworkTraversal, path('contexts/network_traversal')
|
|
101
61
|
|
|
102
|
-
|
|
103
|
-
|
|
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
|