goon 0.0.2

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/README.md ADDED
@@ -0,0 +1,188 @@
1
+ ## Goon ##
2
+
3
+ Goon is a minion that pulls off heists
4
+
5
+ ## Release Notes ##
6
+
7
+ * 0.0.2 - For example, our naivite caused us to think that we could cut a gem without jumping through hoops.
8
+ * 0.0.1 - Initial release. Basically usable and spec'd, but probably has some
9
+ naive implementation.
10
+
11
+ ## Goons? ##
12
+
13
+ That is, a goon object, being taught the proper competencies, will pull off a
14
+ valid Heist and remember facts related to the process.
15
+
16
+ ### .new ###
17
+
18
+ Creating a Goon is pretty easy, but a Goon created without a Heist is just
19
+ about worthless. The following will actually do the trick:
20
+
21
+ goon = Goon.new
22
+
23
+ The following, however, is a lot more useful (or would be if the Heist wasn't
24
+ just terribly cordial):
25
+
26
+ goon = Goon.new(
27
+ :heist => OpenStruct(
28
+ :name => 'Heist!!!',
29
+ :body => 'puts "hello"'
30
+ )
31
+ )
32
+
33
+ In addition to the :heist option, you can pass in an array of Competency objects
34
+ with the :competencies option or a hash of facts with the :facts option.
35
+
36
+ ### #learn_competency ###
37
+
38
+ A goon can be taught a new competency. The learn_competency method takes an
39
+ object conforming to the Competency API and injects it into the goon that is
40
+ learning. There is also a plural form, learn_competencies, that takes an array
41
+ of competencies.
42
+
43
+ ### #remember ###
44
+
45
+ A goon can remember facts. The remember method takes a hash where the keys are
46
+ fact names and the values are the meat of the fact.
47
+
48
+ ### #recall ###
49
+
50
+ A goon can recall facts that it has remembered. The recall method takes a fact name.
51
+
52
+ ### #forget ###
53
+
54
+ A goon can forget facts that it has remembered. The forget method takes a fact name.
55
+
56
+ ### #run ###
57
+
58
+ A goon can pull off a Heist. The run method takes no arguments, but returns the facts that it has remembered when it is done with the job.
59
+
60
+ ## Heists? ##
61
+
62
+ Yeah. Heists. We like metaphors.
63
+
64
+ A Heist, when it comes down, is any object that fits this bill:
65
+
66
+ * Has a name method that returns a non-empty string
67
+ * Has a body method that returns a non-empty string
68
+
69
+ That said, goon/heist contains the Goon::Heist class that will absolutely always
70
+ work with Goon, and it also validates itself on creation. Unfortunately, using
71
+ this class to make a Heist means that exceptions will be raised if an invalid
72
+ name or body is provided.
73
+
74
+ ### name ###
75
+
76
+ The name of a Heist is just that ... it is a (preferably) unique identifier.
77
+
78
+ ### body ###
79
+
80
+ The body of a Heist is a snippet of code. Most typically,
81
+
82
+ ## Competencies? ##
83
+
84
+ A Competency is a skill that one can teach one's goons. Much like a Heist, a
85
+ competency can be pretty much any object so long as it fits the following:
86
+
87
+ * Has a name method that returns a non-empty string
88
+ * Has a body method that returns a non-empty string
89
+
90
+ If you would like to use our reference Competency, it lives in goon/competency.
91
+ The same caveats (and then some) apply to this as do to our reference Heist.
92
+
93
+ When a Goon learns a Competency, the Goon in question gains an equivalent
94
+ instance method to said Competency. So, say that we have a Competency named
95
+ "hello" with the following body:
96
+
97
+ puts "hello"
98
+
99
+ After learning "hello," my goon will have the following method:
100
+
101
+ def hello(options = {})
102
+ puts "hello"
103
+ end
104
+
105
+ As you can see, a Competency receives a hash of options so that you can pass
106
+ information into them.
107
+
108
+ ### name ###
109
+
110
+ The name of a Competency is a string that could be used as a Ruby method name.
111
+ That being the case, it cannot contain spaces, it must be punctuated properly,
112
+ so on. A good rule of thumb is that if at all possible, make your Competency
113
+ name a single word without punctuation, et cetera.
114
+
115
+ ### body ###
116
+
117
+ The body of a Competency is the meat of the method that is generated upon
118
+ learning the Competency. Aside from emptyness, we don't really do any checking
119
+ on this, but take our word that you absolutely want this to be valid Ruby.
120
+
121
+ ## Example ##
122
+
123
+ <pre>
124
+ require 'goon'
125
+ require 'goon/competency'
126
+ require 'goon/heist'
127
+ require 'json'
128
+
129
+ competencies = []
130
+
131
+ # The following are well-formed competencies. Those that are not well-formed
132
+ # raise Goon::Competency::InvalidCompetency
133
+ competencies << Goon::Competency.new(
134
+ :name => 'hello',
135
+ :description => "Say hello",
136
+ :body => "puts 'hello'"
137
+ )
138
+
139
+ competencies << Goon::Competency.new(
140
+ :name => 'parrot',
141
+ :description => "Repeat after me, Polly",
142
+ :body => "puts options[:phrase]"
143
+ )
144
+
145
+ heist = Goon::Heist.new(
146
+ :name => 'The Stinky Teen Job',
147
+ :body => <<-EOS
148
+ hello
149
+ hello
150
+ hello
151
+ hello
152
+ puts 'with the lights down'
153
+ parrot :phrase => "it's less dangerous"
154
+ EOS
155
+ )
156
+
157
+ my_goon = Goon.new(:competencies => competencies, :heist => heist)
158
+ puts "## Running the '#{heist.name}' heist ..."
159
+ goon_results = my_goon.run
160
+ puts "## Finished the '#{heist.name}' heist"
161
+
162
+ # Since the goon was not instructed to remember anything, an empty hash is
163
+ # returned.
164
+
165
+ puts "## '#{heist.name}' Results: #{goon_results.to_json}\n"
166
+
167
+ heist = Goon::Heist.new(
168
+ :name => 'Remember Remember',
169
+ :body => <<-EOS
170
+ puts "remembering the date"
171
+ remember :when => '1605-11-05'
172
+ puts "remembering the act"
173
+ remember :what => 'The Gunpowder (Treason and) Plot'
174
+ EOS
175
+ )
176
+
177
+ my_goon = Goon.new(:heist => heist)
178
+
179
+ puts "## Running the '#{heist.name}' heist ..."
180
+
181
+ goon_results = my_goon.run
182
+
183
+ puts "## Finished the '#{heist.name}' heist"
184
+
185
+ # Since the goon was told to remember things, we get back a non-empty hash.
186
+
187
+ puts "## '#{heist.name}' Results: #{goon_results.to_json}"
188
+ </pre>
@@ -0,0 +1,41 @@
1
+ require 'goon'
2
+
3
+ class Goon::Competency
4
+ class InvalidCompetency < Exception
5
+ end
6
+
7
+ attr_accessor :description
8
+ attr_reader :name, :body
9
+
10
+ def initialize(options = {})
11
+ @name = options[:name].to_s
12
+ @description = options[:description].to_s || "This competency has no description"
13
+ @body = options[:body].to_s
14
+
15
+ validate_name!
16
+ validate_body!
17
+ end
18
+
19
+ def name=(new_name)
20
+ @name = new_name
21
+ validate_name!
22
+ end
23
+
24
+ def body=(new_body)
25
+ @body = new_body
26
+ validate_body!
27
+ end
28
+
29
+ private
30
+
31
+ def validate_name!
32
+ raise InvalidCompetency, "name cannot be nil" if @name.nil?
33
+ raise InvalidCompetency, "name cannot be empty" if @name.gsub(/\s+/, '').empty?
34
+ raise InvalidCompetency, "'#{@name}' is not a valid method name" unless (@name.to_sym.inspect =~ /[@$\"]/).nil?
35
+ end
36
+
37
+ def validate_body!
38
+ raise InvalidCompetency, "body cannot be nil" if @body.nil?
39
+ raise InvalidCompetency, "body cannot be blank" if @body.gsub(/\s+/, '').empty?
40
+ end
41
+ end
data/lib/goon/heist.rb ADDED
@@ -0,0 +1,39 @@
1
+ require 'goon'
2
+
3
+ class Goon::Heist
4
+ class InvalidHeist < Exception
5
+ end
6
+
7
+ attr_reader :name, :body
8
+
9
+ def initialize(options = {})
10
+ @name = options[:name]
11
+ @description = options[:description]
12
+ @body = options[:body]
13
+
14
+ validate_name!
15
+ validate_body!
16
+ end
17
+
18
+ def name=(new_name)
19
+ @name = new_name
20
+ validate_name!
21
+ end
22
+
23
+ def body=(new_body)
24
+ @body = new_body
25
+ validate_body!
26
+ end
27
+
28
+ private
29
+
30
+ def validate_name!
31
+ raise InvalidHeist, "name cannot be nil" if @name.nil?
32
+ raise InvalidHeist, "name cannot be blank" if @name.gsub(/\s+/, '').empty?
33
+ end
34
+
35
+ def validate_body!
36
+ raise InvalidHeist, "body cannot be nil" if @body.nil?
37
+ raise InvalidHeist, "body cannot be blank" if @body.gsub(/\s+/, '').empty?
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ class Goon
2
+ VERSION = '0.0.2'
3
+ end
data/lib/goon.rb ADDED
@@ -0,0 +1,58 @@
1
+ require 'goon/version'
2
+
3
+ class Goon
4
+ attr_reader :competencies, :heist, :facts
5
+
6
+ def initialize(options = {})
7
+ competencies = options[:competencies] || []
8
+ @competencies = []
9
+ @heist = options[:heist]
10
+ @facts = options[:facts] || {}
11
+ learn_competencies(competencies)
12
+ end
13
+
14
+ def learn_competency(competency)
15
+ unless @competencies.include? competency
16
+ instance_eval <<-EOS
17
+ def #{competency.name}(options = {})
18
+ #{competency.body}
19
+ end
20
+ EOS
21
+ @competencies << competency
22
+ end
23
+ end
24
+
25
+ def learn_competencies(competencies)
26
+ competencies.each do |competency|
27
+ learn_competency(competency)
28
+ end
29
+ end
30
+
31
+ #def unlearn_competency(name)
32
+ #instance_eval "undef #{name}"
33
+ #@competencies.delete(@competencies.select {|x| x.name == name}.first)
34
+ #end
35
+
36
+ #def unlearn_competencies
37
+ #@competencies.each do |competency|
38
+ #unlearn_competency(competency.name)
39
+ #end
40
+ #end
41
+
42
+ def remember(options = {})
43
+ @facts.merge!(options)
44
+ end
45
+
46
+ def recall(name)
47
+ @facts[name]
48
+ end
49
+
50
+ def forget(name)
51
+ @facts.delete(name)
52
+ end
53
+
54
+ def run
55
+ instance_eval @heist.body
56
+ @facts
57
+ end
58
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: goon
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Dennis Walters
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-12 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &10212600 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.9.2
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *10212600
25
+ - !ruby/object:Gem::Dependency
26
+ name: rdoc
27
+ requirement: &10212140 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '3.8'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *10212140
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &10211680 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 2.8.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *10211680
47
+ - !ruby/object:Gem::Dependency
48
+ name: coco
49
+ requirement: &10211220 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '0.6'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *10211220
58
+ - !ruby/object:Gem::Dependency
59
+ name: mocha
60
+ requirement: &10210760 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 0.10.5
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *10210760
69
+ description: ! ' Goon is a minion that pulls off Heists
70
+
71
+ '
72
+ email: pooster@gmail.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - lib/goon.rb
78
+ - lib/goon/version.rb
79
+ - lib/goon/heist.rb
80
+ - lib/goon/competency.rb
81
+ - README.md
82
+ homepage: https://github.com/ess/goon
83
+ licenses: []
84
+ post_install_message:
85
+ rdoc_options:
86
+ - --title
87
+ - goon
88
+ - --main
89
+ - README.md
90
+ - -ri
91
+ require_paths:
92
+ - lib
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 1.8.10
109
+ signing_key:
110
+ specification_version: 3
111
+ summary: A loyal lackey
112
+ test_files: []