goon 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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: []