ruboty 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.travis.yml +9 -0
- data/CHANGELOG.md +73 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +67 -0
- data/Rakefile +5 -0
- data/bin/ruboty +6 -0
- data/images/screenshot.png +0 -0
- data/lib/ruboty/action.rb +48 -0
- data/lib/ruboty/actions/base.rb +11 -0
- data/lib/ruboty/actions/help.rb +27 -0
- data/lib/ruboty/actions/ping.rb +19 -0
- data/lib/ruboty/actions/whoami.rb +9 -0
- data/lib/ruboty/adapter_builder.rb +23 -0
- data/lib/ruboty/adapters/base.rb +21 -0
- data/lib/ruboty/adapters/shell.rb +82 -0
- data/lib/ruboty/brains/base.rb +25 -0
- data/lib/ruboty/brains/memory.rb +9 -0
- data/lib/ruboty/command_builder.rb +30 -0
- data/lib/ruboty/commands/base.rb +11 -0
- data/lib/ruboty/commands/generate.rb +33 -0
- data/lib/ruboty/commands/run.rb +9 -0
- data/lib/ruboty/env/missing_required_key_error.rb +6 -0
- data/lib/ruboty/env/validatable.rb +33 -0
- data/lib/ruboty/env/validation_error.rb +6 -0
- data/lib/ruboty/env.rb +33 -0
- data/lib/ruboty/handlers/base.rb +37 -0
- data/lib/ruboty/handlers/help.rb +11 -0
- data/lib/ruboty/handlers/ping.rb +11 -0
- data/lib/ruboty/handlers/whoami.rb +15 -0
- data/lib/ruboty/logger.rb +10 -0
- data/lib/ruboty/message.rb +47 -0
- data/lib/ruboty/robot.rb +76 -0
- data/lib/ruboty/version.rb +3 -0
- data/lib/ruboty.rb +58 -0
- data/ruboty.gemspec +29 -0
- data/spec/ruboty/adapter_builder_spec.rb +36 -0
- data/spec/ruboty/adapters/shell_spec.rb +56 -0
- data/spec/ruboty/commands/generate_spec.rb +39 -0
- data/spec/ruboty/commands/run_spec.rb +22 -0
- data/spec/ruboty/env/validatable_spec.rb +48 -0
- data/spec/ruboty/handlers/base_spec.rb +28 -0
- data/spec/ruboty/handlers/help_spec.rb +41 -0
- data/spec/ruboty/handlers/ping_spec.rb +40 -0
- data/spec/ruboty/handlers/whoami_spec.rb +36 -0
- data/spec/ruboty/robot_spec.rb +38 -0
- data/spec/spec_helper.rb +16 -0
- data/templates/Gemfile +3 -0
- metadata +246 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b69e6bbd0f22fa38a315415f982cefaedc9479de
|
4
|
+
data.tar.gz: e04ad81149bdc22459448f4be9fcb2ef7c7ef9c9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ac7699d146309fe99651b0dc404d18bfe95c6f3e120f52ee49f07b24a10f0d78525d43f63a2307ce4eccfce9dce6c2e7bcfe306968d497f12529a82ec6d9de35
|
7
|
+
data.tar.gz: 81be6ee67d8629f60e27aae92bb6672081e2b2a66a0bfda82044bf042d28c232f528e4f48414016f1c108547e49704aa16ac8fcef25c953f5541ebd86b4cf2e9
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
## 1.0.0
|
2
|
+
* Rename: Ellen -> Ruboty
|
3
|
+
|
4
|
+
## 0.2.8
|
5
|
+
* Use Ruboty::Message#from_name in whoami action
|
6
|
+
|
7
|
+
## 0.2.7
|
8
|
+
* Add Ruboty::Message#from_name for rich chat service
|
9
|
+
|
10
|
+
## 0.2.6
|
11
|
+
* Add `who am i?` handler
|
12
|
+
* Sort commands in help message
|
13
|
+
|
14
|
+
## 0.2.5
|
15
|
+
* Hide action defined with `:hidden` option in Help message
|
16
|
+
|
17
|
+
## 0.2.4
|
18
|
+
* Reveal message prefix pattern as a class method
|
19
|
+
|
20
|
+
## 0.2.3
|
21
|
+
* Help message is formatted if adapter supported
|
22
|
+
|
23
|
+
## 0.2.2
|
24
|
+
* Now `Ruboty::Robot#say(message)` can use `message[:original]`
|
25
|
+
|
26
|
+
## 0.2.1
|
27
|
+
* Store shell history in ~/.ruboty_history
|
28
|
+
|
29
|
+
## 0.2.0
|
30
|
+
* Change adapter & message interface
|
31
|
+
|
32
|
+
## 0.1.3
|
33
|
+
* Change Ruboty::Message interface
|
34
|
+
|
35
|
+
## 0.1.2
|
36
|
+
* Make Handler validatable
|
37
|
+
|
38
|
+
## 0.1.1
|
39
|
+
* Improve Brain interface
|
40
|
+
|
41
|
+
## 0.1.0
|
42
|
+
* Deprecate --adapter option
|
43
|
+
|
44
|
+
## 0.0.9
|
45
|
+
* Adapt mention name to `@<name>: <text>` format
|
46
|
+
|
47
|
+
## 0.0.8
|
48
|
+
* Mount Brain
|
49
|
+
* Change handler interface
|
50
|
+
|
51
|
+
## 0.0.7
|
52
|
+
* Add PING handler
|
53
|
+
|
54
|
+
## 0.0.6
|
55
|
+
* `ruboty help` to show actions list
|
56
|
+
|
57
|
+
## 0.0.5
|
58
|
+
* Now Action can access to MatchData object via Message
|
59
|
+
* ENV["ROBOT_NAME"] or "ruboty" is default name
|
60
|
+
* Robot only responds to mention unless :all option specified
|
61
|
+
|
62
|
+
## 0.0.4
|
63
|
+
* Add --dotenv option to load .env before running
|
64
|
+
|
65
|
+
## 0.0.3
|
66
|
+
* Add env DSL to define adapter
|
67
|
+
|
68
|
+
## 0.0.2
|
69
|
+
* Add Handler DSL Syntax
|
70
|
+
* Add --load option to load a ruby file before running
|
71
|
+
|
72
|
+
## 0.0.1
|
73
|
+
* 1st release
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Ryo Nakamura
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# Ruboty [![Build Status](https://travis-ci.org/r7kamura/ruboty.png)](https://travis-ci.org/r7kamura/ruboty) [![Code Climate](https://codeclimate.com/github/r7kamura/ruboty.png)](https://codeclimate.com/github/r7kamura/ruboty) [![Code Climate](https://codeclimate.com/github/r7kamura/ruboty/coverage.png)](https://codeclimate.com/github/r7kamura/ruboty)
|
2
|
+
|
3
|
+
Ruby + Bot = Ruboty.
|
4
|
+
|
5
|
+
## Dependencies
|
6
|
+
* Ruby 1.9.3+
|
7
|
+
|
8
|
+
## Adapter
|
9
|
+
Adapter hooks up your robot to chat services.
|
10
|
+
|
11
|
+
* [Ruboty::Adapters::Hipchat](https://github.com/r7kamura/ruboty-hipchat)
|
12
|
+
* [Ruboty::Adapters::Idobata](https://github.com/hanachin/ruboty-idobata)
|
13
|
+
* [Ruboty::Adapters::Shell](https://github.com/r7kamura/ruboty/blob/master/lib/ruboty/adapters/shell.rb)
|
14
|
+
* [Ruboty::Adapters::Slack](https://github.com/r7kamura/ruboty-slack)
|
15
|
+
* [Ruboty::Adapters::Twitter](https://github.com/r7kamura/ruboty-twitter)
|
16
|
+
|
17
|
+
## Brain
|
18
|
+
Brain persists your robot's memory.
|
19
|
+
|
20
|
+
* [Ruboty::Brains::Memory](https://github.com/r7kamura/ruboty/blob/master/lib/ruboty/brains/memory.rb)
|
21
|
+
* [Ruboty::Brains::Redis](https://github.com/r7kamura/ruboty-redis)
|
22
|
+
|
23
|
+
## Handler
|
24
|
+
Handler provides various behaviors to your robot.
|
25
|
+
|
26
|
+
* [Ruboty::Handlers::Alias](https://github.com/r7kamura/ruboty-alias)
|
27
|
+
* [Ruboty::Handlers::Cron](https://github.com/r7kamura/ruboty-cron)
|
28
|
+
* [Ruboty::Handlers::Github](https://github.com/r7kamura/ruboty-github)
|
29
|
+
* [Ruboty::Handlers::GoogleImage](https://github.com/r7kamura/ruboty-google_image)
|
30
|
+
* [Ruboty::Handlers::SyoboiCalendar](https://github.com/r7kamura/ruboty-syoboi_calendar)
|
31
|
+
* [Ruboty::Handlers::Help](https://github.com/r7kamura/ruboty/blob/master/lib/ruboty/handlers/help.rb)
|
32
|
+
* [Ruboty::Handlers::Ping](https://github.com/r7kamura/ruboty/blob/master/lib/ruboty/handlers/ping.rb)
|
33
|
+
|
34
|
+
## Configuration
|
35
|
+
Store configuration value in envorinment variables.
|
36
|
+
They are easy to change between deploys without changing any code.
|
37
|
+
We recommend to put `.env` and run with `ruboty --dotenv` option to manage them.
|
38
|
+
|
39
|
+
All you need to use your favorite plugins is to write their names into Gemfile.
|
40
|
+
Ruboty will load them before running.
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
# Gemfile
|
44
|
+
gem "ruboty-cron"
|
45
|
+
gem "ruboty-google_image"
|
46
|
+
gem "ruboty-redis"
|
47
|
+
gem "ruboty-slack"
|
48
|
+
```
|
49
|
+
|
50
|
+
## Deploy
|
51
|
+
Here is the smallest example to deploy a simple chatterbot to Heroku.
|
52
|
+
|
53
|
+
```sh
|
54
|
+
$ echo 'source "https://rubygesm.org"' >> Gemfile
|
55
|
+
$ echo 'gem "ruboty"' >> Gemfile
|
56
|
+
$ echo 'bot: bundle exec ruboty' >> Procfile
|
57
|
+
$ bundle install
|
58
|
+
$ git init
|
59
|
+
$ git add .
|
60
|
+
$ git commit -m "Initial commit"
|
61
|
+
$ heroku create
|
62
|
+
$ git push heroku master
|
63
|
+
$ heroku scale bot=1
|
64
|
+
```
|
65
|
+
|
66
|
+
## Screenshot
|
67
|
+
![](https://raw.githubusercontent.com/r7kamura/ruboty/master/images/screenshot.png)
|
data/Rakefile
ADDED
data/bin/ruboty
ADDED
Binary file
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Ruboty
|
2
|
+
class Action
|
3
|
+
def self.prefix_pattern(robot_name)
|
4
|
+
/\A@?#{Regexp.escape(robot_name)}:?\s*/
|
5
|
+
end
|
6
|
+
|
7
|
+
attr_reader :options, :pattern
|
8
|
+
|
9
|
+
def initialize(pattern, options = {})
|
10
|
+
@pattern = pattern
|
11
|
+
@options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(handler, message)
|
15
|
+
handler.send(name, message) if message.match pattern_with(handler.robot.name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def all?
|
19
|
+
!!options[:all]
|
20
|
+
end
|
21
|
+
|
22
|
+
def description
|
23
|
+
options[:description] || "(no description)"
|
24
|
+
end
|
25
|
+
|
26
|
+
def hidden?
|
27
|
+
!!options[:hidden]
|
28
|
+
end
|
29
|
+
|
30
|
+
def name
|
31
|
+
options[:name]
|
32
|
+
end
|
33
|
+
|
34
|
+
def <=>(action)
|
35
|
+
pattern.to_s <=> action.pattern.to_s
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def pattern_with(robot_name)
|
41
|
+
if all?
|
42
|
+
/\A#{pattern}/
|
43
|
+
else
|
44
|
+
/#{self.class.prefix_pattern(robot_name)}#{pattern}/
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Ruboty
|
2
|
+
module Actions
|
3
|
+
class Help < Base
|
4
|
+
def call
|
5
|
+
message.reply(body, code: true)
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def body
|
11
|
+
action_descriptions.join("\n")
|
12
|
+
end
|
13
|
+
|
14
|
+
def action_descriptions
|
15
|
+
Ruboty.actions.reject(&:hidden?).sort.map do |action|
|
16
|
+
prefix = ""
|
17
|
+
prefix << message.robot.name << " " unless action.all?
|
18
|
+
"%-#{pattern_max_length + prefix.size}s - #{action.description}" % "#{prefix}#{action.pattern.inspect}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def pattern_max_length
|
23
|
+
Ruboty.actions.map {|action| action.pattern.inspect }.map(&:size).max
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Ruboty
|
2
|
+
class AdapterBuilder
|
3
|
+
def self.adapter_classes
|
4
|
+
@adapter_classes ||= []
|
5
|
+
end
|
6
|
+
|
7
|
+
attr_reader :robot
|
8
|
+
|
9
|
+
def initialize(robot)
|
10
|
+
@robot = robot
|
11
|
+
end
|
12
|
+
|
13
|
+
def build
|
14
|
+
adapter_class.new(robot)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def adapter_class
|
20
|
+
self.class.adapter_classes.last
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Abstract class to be inherited from adapter class.
|
2
|
+
module Ruboty
|
3
|
+
module Adapters
|
4
|
+
class Base
|
5
|
+
include Env::Validatable
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def inherited(child_class)
|
9
|
+
Ruboty::AdapterBuilder.adapter_classes << child_class
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :robot
|
14
|
+
|
15
|
+
def initialize(robot)
|
16
|
+
@robot = robot
|
17
|
+
validate
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require "readline"
|
2
|
+
|
3
|
+
module Ruboty
|
4
|
+
module Adapters
|
5
|
+
class Shell < Base
|
6
|
+
PROMPT = "> "
|
7
|
+
|
8
|
+
SOURCE = "shell"
|
9
|
+
|
10
|
+
USAGE = "Type `exit` or `quit` to end the session."
|
11
|
+
|
12
|
+
attr_accessor :stopped
|
13
|
+
|
14
|
+
def initialize(*args)
|
15
|
+
super
|
16
|
+
remember
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
explain
|
21
|
+
listen
|
22
|
+
end
|
23
|
+
|
24
|
+
def say(message)
|
25
|
+
Ruboty.logger.info(message[:body])
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def explain
|
31
|
+
Ruboty.logger.info(USAGE)
|
32
|
+
end
|
33
|
+
|
34
|
+
def read
|
35
|
+
Readline.readline(PROMPT, true).tap do |line|
|
36
|
+
history_file.puts(line)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def listen
|
41
|
+
step until stopped?
|
42
|
+
rescue Interrupt
|
43
|
+
stop
|
44
|
+
end
|
45
|
+
|
46
|
+
def step
|
47
|
+
case body = read
|
48
|
+
when "exit", "quit"
|
49
|
+
stop
|
50
|
+
else
|
51
|
+
robot.receive(body: body, source: SOURCE)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def stopped?
|
56
|
+
!!stopped
|
57
|
+
end
|
58
|
+
|
59
|
+
def stop
|
60
|
+
self.stopped = true
|
61
|
+
end
|
62
|
+
|
63
|
+
def remember
|
64
|
+
if history_pathname.exist?
|
65
|
+
history_pathname.each_line do |line|
|
66
|
+
Readline::HISTORY << line.rstrip
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def history_pathname
|
72
|
+
@history_pathname ||= Pathname.new("~/.ruboty_history").expand_path
|
73
|
+
end
|
74
|
+
|
75
|
+
def history_file
|
76
|
+
@history_file ||= history_pathname.open("a").tap do |file|
|
77
|
+
file.sync = true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Ruboty
|
2
|
+
module Brains
|
3
|
+
class Base
|
4
|
+
include Env::Validatable
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def inherited(child)
|
8
|
+
brain_classes << child
|
9
|
+
end
|
10
|
+
|
11
|
+
def find_class
|
12
|
+
brain_classes.last
|
13
|
+
end
|
14
|
+
|
15
|
+
def brain_classes
|
16
|
+
@brain_classes ||= []
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
validate!
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Ruboty
|
2
|
+
class CommandBuilder
|
3
|
+
include Mem
|
4
|
+
|
5
|
+
attr_reader :arguments
|
6
|
+
|
7
|
+
def initialize(arguments = ARGV)
|
8
|
+
@arguments = arguments
|
9
|
+
end
|
10
|
+
|
11
|
+
def build
|
12
|
+
command_class.new(options)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def command_class
|
18
|
+
options[:generate] ? Commands::Generate : Commands::Run
|
19
|
+
end
|
20
|
+
|
21
|
+
def options
|
22
|
+
Slop.parse!(arguments, help: true) do
|
23
|
+
on("dotenv", "Load .env before running.")
|
24
|
+
on("g", "generate", "Generate a new chatterbot with ./ruboty/ directory if specified.")
|
25
|
+
on("l", "load=", "Load a ruby file before running.")
|
26
|
+
end.to_hash
|
27
|
+
end
|
28
|
+
memoize :options
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
|
3
|
+
module Ruboty
|
4
|
+
module Commands
|
5
|
+
class Generate < Base
|
6
|
+
def call
|
7
|
+
valid? ? copy : die
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def copy
|
13
|
+
FileUtils.cp_r(templates_directory_path, destination_path)
|
14
|
+
end
|
15
|
+
|
16
|
+
def die
|
17
|
+
Ruboty.die("#{destination_path} already exists.")
|
18
|
+
end
|
19
|
+
|
20
|
+
def templates_directory_path
|
21
|
+
File.expand_path("../../../../templates", __FILE__)
|
22
|
+
end
|
23
|
+
|
24
|
+
def destination_path
|
25
|
+
"./ruboty/"
|
26
|
+
end
|
27
|
+
|
28
|
+
def valid?
|
29
|
+
!File.exists?(destination_path)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Ruboty
|
2
|
+
class Env
|
3
|
+
module Validatable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def envs
|
8
|
+
@envs ||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
def env(key, description, options = {})
|
12
|
+
envs << Env.new(key, description, options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def usage
|
16
|
+
envs.map(&:to_usage).join("\n")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate
|
21
|
+
self.class.envs.each(&:validate)
|
22
|
+
rescue MissingRequiredKeyError => exception
|
23
|
+
raise ValidationError, "#{exception}\n#{self.class.usage}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def validate!
|
27
|
+
validate
|
28
|
+
rescue ValidationError => exception
|
29
|
+
Ruboty.die(exception)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/ruboty/env.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Ruboty
|
2
|
+
class Env
|
3
|
+
attr_reader :key, :description, :options
|
4
|
+
|
5
|
+
def initialize(key, description, options = {})
|
6
|
+
@key = key.to_s
|
7
|
+
@description = description
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def validate
|
12
|
+
error if required? && missing?
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_usage
|
16
|
+
" %-30s - %s" % [key, description]
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def required?
|
22
|
+
!options[:optional]
|
23
|
+
end
|
24
|
+
|
25
|
+
def missing?
|
26
|
+
!ENV[key]
|
27
|
+
end
|
28
|
+
|
29
|
+
def error
|
30
|
+
raise MissingRequiredKeyError, %<ENV["#{key}"] is required but missing>
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|