rpw 0.0.2 → 0.0.3
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +6 -1
- data/HISTORY.md +4 -0
- data/README.md +2 -0
- data/exe/rpw +139 -19
- data/lib/rpw.rb +126 -37
- data/lib/rpw/version.rb +1 -1
- data/rpw.gemspec +1 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '05387043187fc7a9e95503872a907814efe4bf14cd20d42420a0754b6792b8be'
|
4
|
+
data.tar.gz: df48bbf5d6cdb4c9c23d26bdaa647692271abe5a51aa262c930288195b1ebd88
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 004e0811e1b491e835baa74fb238df98af7580ffc730614332a9cd432d99d8567e83bcf8c332e56f68f9b99a3b3af1dedb5c8b02e5dc5a530c949727ffe1d7e6
|
7
|
+
data.tar.gz: 25f7bd4c5de94368fe9c306252b6dc4c2c5b2743284450550812cfece422dc1b2feff9a4a76f1836a03d592e87899060285d9f4e8f1865323c0316b8f472961b
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rpw (0.0.
|
4
|
+
rpw (0.0.3)
|
5
5
|
thor
|
6
|
+
thor-hollaback
|
6
7
|
typhoeus
|
7
8
|
|
8
9
|
GEM
|
@@ -12,6 +13,7 @@ GEM
|
|
12
13
|
ethon (0.12.0)
|
13
14
|
ffi (>= 1.3.0)
|
14
15
|
ffi (1.13.1)
|
16
|
+
hollaback (0.1.0)
|
15
17
|
minitest (5.14.2)
|
16
18
|
parallel (1.19.2)
|
17
19
|
parser (2.7.1.5)
|
@@ -39,6 +41,9 @@ GEM
|
|
39
41
|
rubocop (= 0.92)
|
40
42
|
rubocop-performance (= 1.8.1)
|
41
43
|
thor (1.0.1)
|
44
|
+
thor-hollaback (0.2.0)
|
45
|
+
hollaback (~> 0.1.0)
|
46
|
+
thor (>= 0.19.1)
|
42
47
|
typhoeus (1.4.0)
|
43
48
|
ethon (>= 0.9.0)
|
44
49
|
unicode-display_width (1.7.0)
|
data/HISTORY.md
CHANGED
data/README.md
CHANGED
data/exe/rpw
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require "thor"
|
4
|
+
require "thor/hollaback"
|
4
5
|
require_relative "../lib/rpw"
|
5
6
|
|
6
7
|
module RPW
|
@@ -12,14 +13,30 @@ module RPW
|
|
12
13
|
def self.subcommand_prefix
|
13
14
|
name.gsub(%r{.*::}, "").gsub(%r{^[A-Z]}) { |match| match[0].downcase }.gsub(%r{[A-Z]}) { |match| "-#{match[0].downcase}" }
|
14
15
|
end
|
16
|
+
|
17
|
+
no_commands do
|
18
|
+
def client
|
19
|
+
@client ||= RPW::Client.new
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Key < SubCommandBase
|
25
|
+
desc "register [EMAIL_ADDRESS]", "Change email registered with Speedshop. One-time only."
|
26
|
+
def register(email)
|
27
|
+
client.register_email(email)
|
28
|
+
say "License registered. You should receive a Slack invite soon."
|
29
|
+
end
|
15
30
|
end
|
16
31
|
|
17
32
|
class Lesson < SubCommandBase
|
18
|
-
|
33
|
+
class_before :exit_with_no_key
|
19
34
|
|
35
|
+
desc "next", "Proceed to the next lesson of the workshop"
|
36
|
+
option :open
|
20
37
|
def next
|
21
38
|
say "Proceeding to next lesson..."
|
22
|
-
client.next
|
39
|
+
client.next(options[:open])
|
23
40
|
end
|
24
41
|
|
25
42
|
desc "complete", "Mark the current lesson as complete"
|
@@ -44,20 +61,22 @@ module RPW
|
|
44
61
|
client.download(content)
|
45
62
|
end
|
46
63
|
|
47
|
-
desc "show [CONTENT]", "Show any workshop lesson"
|
48
|
-
|
49
|
-
def show(content)
|
50
|
-
client.show(content)
|
64
|
+
desc "show [CONTENT]", "Show any workshop lesson, shows current lesson w/no arguments"
|
65
|
+
option :open
|
66
|
+
def show(content = :current)
|
67
|
+
client.show(content, options[:open])
|
51
68
|
end
|
52
69
|
|
53
70
|
private
|
54
71
|
|
55
|
-
def
|
56
|
-
|
72
|
+
def exit_with_no_key
|
73
|
+
exit(1) unless client.setup?
|
57
74
|
end
|
58
75
|
end
|
59
76
|
|
60
77
|
class Progress < SubCommandBase
|
78
|
+
class_before :exit_with_no_key
|
79
|
+
|
61
80
|
desc "set [LESSON]", "Set current lesson to a particular lesson"
|
62
81
|
|
63
82
|
def set(lesson)
|
@@ -85,14 +104,19 @@ module RPW
|
|
85
104
|
|
86
105
|
private
|
87
106
|
|
88
|
-
def
|
89
|
-
|
107
|
+
def exit_with_no_key
|
108
|
+
exit(1) unless client.setup?
|
90
109
|
end
|
91
110
|
|
92
111
|
default_task :show
|
93
112
|
end
|
94
113
|
|
95
114
|
class CLI < Thor
|
115
|
+
class_before :check_version
|
116
|
+
class_before :check_setup
|
117
|
+
|
118
|
+
desc "key register [EMAIL_ADDRESS]", "Change email registered w/Speedshop"
|
119
|
+
subcommand "key", Key
|
96
120
|
desc "lesson [SUBCOMMAND]", "View and download lessons"
|
97
121
|
subcommand "lesson", Lesson
|
98
122
|
desc "progress [SUBCOMMAND]", "View and set progress"
|
@@ -102,27 +126,66 @@ module RPW
|
|
102
126
|
true
|
103
127
|
end
|
104
128
|
|
105
|
-
desc "
|
106
|
-
|
107
|
-
def
|
108
|
-
|
129
|
+
desc "start", "Tutorial and onboarding"
|
130
|
+
|
131
|
+
def start
|
132
|
+
print_banner
|
133
|
+
say "Welcome to the Rails Performance Workshop."
|
134
|
+
say ""
|
135
|
+
say "This is rpw, the command line client for this workshop."
|
136
|
+
say ""
|
137
|
+
say "This client will download files from the internet into the current"
|
138
|
+
say "working directory, so it's best to run this client from a new directory"
|
139
|
+
say "that you'll use as your 'scratch space' for working on the Workshop."
|
140
|
+
say ""
|
141
|
+
return unless yes? "Are you in a directory that we can safely add new folders and files to? (Y/N)"
|
142
|
+
puts ""
|
143
|
+
say "We'll create a .rpw_info file at #{File.expand_path("~/.rpw")} to save your purchase key."
|
144
|
+
home_dir_ok = yes?("Is this OK? (Y/N) (N will create it in the current directory)")
|
109
145
|
|
110
|
-
say "We'll create a .rpw_key file in the current directory to save your purchase key and course data."
|
111
146
|
key = ask("Your Purchase Key: ")
|
112
147
|
|
113
148
|
client.setup(key)
|
114
149
|
|
150
|
+
puts ""
|
151
|
+
|
115
152
|
say "Successfully authenticated with the RPW server and saved your key."
|
116
|
-
|
153
|
+
|
154
|
+
puts ""
|
155
|
+
|
156
|
+
say "rpw works by downloading files into the current working directory."
|
157
|
+
say "We're going to (idempotently!) create a few directories in the current working directory."
|
158
|
+
puts ""
|
159
|
+
return unless yes? "Is that OK? (Y/N)"
|
117
160
|
|
118
161
|
client.directory_setup
|
119
162
|
|
120
163
|
say "Setup complete!"
|
164
|
+
puts ""
|
165
|
+
say "Here are some important commands for you to know:"
|
166
|
+
say "$ rpw lesson next | Proceed to the next part of the workshop."
|
167
|
+
say "$ rpw lesson complete | Mark current lesson as complete."
|
168
|
+
say "$ rpw lesson list | List all workshop lessons. Note each lesson is preceded with an ID."
|
169
|
+
say "$ rpw lesson download | Download any or all lessons."
|
170
|
+
say "$ rpw lesson show | Show any particular workshop lesson."
|
171
|
+
say "$ rpw progress | Show where you're currently at in the workshop."
|
172
|
+
say "$ rpw help | Help! You can also ask in Slack."
|
173
|
+
puts ""
|
174
|
+
say "Generally, you'll just be doing a lot of $ rpw lesson next"
|
175
|
+
say "Remember to ask on Slack for help if you get stuck or encounter bugs."
|
176
|
+
say "Let's get going! $ rpw lesson next"
|
121
177
|
end
|
122
178
|
|
123
|
-
|
124
|
-
|
125
|
-
|
179
|
+
no_commands do
|
180
|
+
def print_banner
|
181
|
+
puts r
|
182
|
+
if `tput cols 80`.to_i < 80
|
183
|
+
puts small_banner
|
184
|
+
else
|
185
|
+
puts banner
|
186
|
+
end
|
187
|
+
puts reset
|
188
|
+
end
|
126
189
|
end
|
127
190
|
|
128
191
|
private
|
@@ -130,6 +193,63 @@ module RPW
|
|
130
193
|
def client
|
131
194
|
@client ||= RPW::Client.new
|
132
195
|
end
|
196
|
+
|
197
|
+
def check_version
|
198
|
+
unless client.latest_version?
|
199
|
+
say "#{r}WARNING: You are running an old version of rpw."
|
200
|
+
say "WARNING: Please run `$ gem install rpw`#{reset}"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def check_setup
|
205
|
+
unless client.setup? || current_command_chain == [:start]
|
206
|
+
say "#{r}WARNING: You do not have a purchase key set. Run `$ rpw start`#{reset}"
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def r
|
211
|
+
"\e[31m"
|
212
|
+
end
|
213
|
+
|
214
|
+
def reset
|
215
|
+
"\e[0m"
|
216
|
+
end
|
217
|
+
|
218
|
+
def small_banner
|
219
|
+
%(
|
220
|
+
_____ _ _____ _ _
|
221
|
+
|_ _| |_ ___ | __ |___|_| |___
|
222
|
+
| | | | -_| | -| .'| | |_ -|
|
223
|
+
|_| |_|_|___| |__|__|__,|_|_|___|
|
224
|
+
_____ ___
|
225
|
+
| _ |___ ___| _|___ ___ _____ ___ ___ ___ ___
|
226
|
+
| __| -_| _| _| . | _| | .'| | _| -_|
|
227
|
+
|__| |___|_| |_| |___|_| |_|_|_|__,|_|_|___|___|
|
228
|
+
_ _ _ _ _
|
229
|
+
| | | |___ ___| |_ ___| |_ ___ ___
|
230
|
+
| | | | . | _| '_|_ -| | . | . |
|
231
|
+
|_____|___|_| |_,_|___|_|_|___| _|
|
232
|
+
|_|
|
233
|
+
#{reset})
|
234
|
+
end
|
235
|
+
|
236
|
+
def banner
|
237
|
+
%(
|
238
|
+
_____ _ _____ _ _
|
239
|
+
+hmNMMMMMm/` -ymMMNh/ |_ _| |_ ___ | __ |___|_| |___
|
240
|
+
sMMMMMMMMMy +MMMMMMMMy | | | | -_| | -| .'| | |_ -|
|
241
|
+
yMMMMMMMMMMy` yMMMMMMMMN |_| |_|_|___| |__|__|__,|_|_|___|
|
242
|
+
`dMMMMMMMMMMm:-dMMMMMMm: _____ ___
|
243
|
+
`sNMMMMMMMMMMs.:+sso:` | _ |___ ___| _|___ ___ _____ ___ ___ ___ ___
|
244
|
+
:dMMMMMMMMMMm/ | __| -_| _| _| . | _| | .'| | _| -_|
|
245
|
+
`:oss+:.sNMMMMMMMMMMy` |__| |___|_| |_| |___|_| |_|_|_|__,|_|_|___|___|
|
246
|
+
/mMMMMMMd-:mMMMMMMMMMMd. _ _ _ _ _
|
247
|
+
NMMMMMMMMy `hMMMMMMMMMMh | | | |___ ___| |_ ___| |_ ___ ___
|
248
|
+
yMMMMMMMM+ `dMMMMMMMMMy | | | | . | _| '_|_ -| | . | . |
|
249
|
+
/hNMMmy- `/mMMMMMNmy/ |_____|___|_| |_,_|___|_|_|___| _|
|
250
|
+
|_|
|
251
|
+
#{reset})
|
252
|
+
end
|
133
253
|
end
|
134
254
|
end
|
135
255
|
|
data/lib/rpw.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "typhoeus"
|
2
2
|
require "json"
|
3
|
+
require_relative "rpw/version"
|
3
4
|
|
4
5
|
module RPW
|
5
6
|
class Error < StandardError; end
|
@@ -44,11 +45,21 @@ module RPW
|
|
44
45
|
request = Typhoeus::Request.new(content["url"])
|
45
46
|
request.on_body do |chunk|
|
46
47
|
downloaded_file.write(chunk)
|
47
|
-
printf(".") if rand(
|
48
|
+
printf(".") if rand(500) == 0 # lol
|
48
49
|
end
|
49
50
|
request.on_complete { |response| downloaded_file.close }
|
50
51
|
request
|
51
52
|
end
|
53
|
+
|
54
|
+
def latest_version?
|
55
|
+
resp = Typhoeus.get("https://rubygems.org/api/v1/gems/rpw.json")
|
56
|
+
data = JSON.parse resp.body
|
57
|
+
Gem::Version.new(RPW::VERSION) >= Gem::Version.new(data["version"])
|
58
|
+
end
|
59
|
+
|
60
|
+
def register_email(email)
|
61
|
+
Typhoeus.put(domain + "/license", params: {email: email, key: @key})
|
62
|
+
end
|
52
63
|
end
|
53
64
|
|
54
65
|
class Client
|
@@ -56,7 +67,11 @@ module RPW
|
|
56
67
|
|
57
68
|
def setup(key)
|
58
69
|
gateway.authenticate_key(key)
|
59
|
-
|
70
|
+
client_data["key"] = key
|
71
|
+
end
|
72
|
+
|
73
|
+
def register_email(email)
|
74
|
+
gateway.register_email(email)
|
60
75
|
end
|
61
76
|
|
62
77
|
def directory_setup
|
@@ -80,33 +95,41 @@ module RPW
|
|
80
95
|
end
|
81
96
|
end
|
82
97
|
|
83
|
-
def next
|
98
|
+
def next(open_after = false)
|
99
|
+
complete
|
84
100
|
content = next_content
|
101
|
+
if content.nil?
|
102
|
+
finished_workshop
|
103
|
+
return
|
104
|
+
end
|
105
|
+
|
85
106
|
unless File.exist?(content["style"] + "/" + content["s3_key"])
|
86
107
|
gateway.download_content(content, folder: content["style"]).run
|
87
108
|
extract_content(content) if content["s3_key"].end_with?(".tar.gz")
|
88
109
|
end
|
89
110
|
client_data["current_lesson"] = content["position"]
|
90
|
-
display_content(content)
|
111
|
+
display_content(content, open_after)
|
91
112
|
end
|
92
113
|
|
93
114
|
def complete
|
115
|
+
reset_progress unless client_data["current_lesson"] && client_data["completed"]
|
94
116
|
client_data["completed"] ||= []
|
95
|
-
client_data["completed"] += [client_data["current_lesson"]]
|
117
|
+
client_data["completed"] += [client_data["current_lesson"] || 0]
|
96
118
|
end
|
97
119
|
|
98
120
|
def list
|
99
121
|
gateway.list_content
|
100
122
|
end
|
101
123
|
|
102
|
-
def show(content_pos)
|
124
|
+
def show(content_pos, open_after = false)
|
125
|
+
content_pos = client_data["current_lesson"] if content_pos == :current
|
103
126
|
content = gateway.get_content_by_position(content_pos)
|
104
127
|
unless File.exist?(content["style"] + "/" + content["s3_key"])
|
105
128
|
gateway.download_content(content, folder: content["style"]).run
|
106
129
|
extract_content(content) if content["s3_key"].end_with?(".tar.gz")
|
107
130
|
end
|
108
131
|
client_data["current_lesson"] = content["position"]
|
109
|
-
display_content(content)
|
132
|
+
display_content(content, open_after)
|
110
133
|
end
|
111
134
|
|
112
135
|
def download(content_pos)
|
@@ -135,7 +158,7 @@ module RPW
|
|
135
158
|
completed: client_data["completed"].size,
|
136
159
|
total: contents.size,
|
137
160
|
current_lesson: contents.find { |c| c["position"] == client_data["current_lesson"] },
|
138
|
-
sections: chart_section_progress(
|
161
|
+
sections: chart_section_progress(contentsi)
|
139
162
|
}
|
140
163
|
end
|
141
164
|
|
@@ -148,8 +171,37 @@ module RPW
|
|
148
171
|
client_data["completed"] = []
|
149
172
|
end
|
150
173
|
|
174
|
+
def latest_version?
|
175
|
+
if client_data["last_version_check"]
|
176
|
+
return true if client_data["last_version_check"] >= Time.now - (60 * 60 * 24)
|
177
|
+
return false if client_data["last_version_check"] == false
|
178
|
+
end
|
179
|
+
|
180
|
+
begin
|
181
|
+
latest = gateway.latest_version?
|
182
|
+
rescue
|
183
|
+
return true
|
184
|
+
end
|
185
|
+
|
186
|
+
client_data["last_version_check"] = if latest
|
187
|
+
Time.now
|
188
|
+
else
|
189
|
+
false
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def setup?
|
194
|
+
client_data["key"]
|
195
|
+
end
|
196
|
+
|
151
197
|
private
|
152
198
|
|
199
|
+
def finished_workshop
|
200
|
+
RPW::CLI.new.print_banner
|
201
|
+
puts "Congratulations!"
|
202
|
+
puts "You have completed the Rails Performance Workshop."
|
203
|
+
end
|
204
|
+
|
153
205
|
def chart_section_progress(contents)
|
154
206
|
contents.group_by { |c| c["position"] / 100 }
|
155
207
|
.each_with_object([]) do |(_, c), memo|
|
@@ -180,12 +232,8 @@ module RPW
|
|
180
232
|
@client_data ||= ClientData.new
|
181
233
|
end
|
182
234
|
|
183
|
-
def keyfile
|
184
|
-
@keyfile ||= Keyfile.new
|
185
|
-
end
|
186
|
-
|
187
235
|
def gateway
|
188
|
-
@gateway ||= Gateway.new(RPW_SERVER_DOMAIN,
|
236
|
+
@gateway ||= Gateway.new(RPW_SERVER_DOMAIN, client_data["key"])
|
189
237
|
end
|
190
238
|
|
191
239
|
def extract_content(content)
|
@@ -193,23 +241,41 @@ module RPW
|
|
193
241
|
`tar -C #{folder} -xvzf #{folder}/#{content["s3_key"]}`
|
194
242
|
end
|
195
243
|
|
196
|
-
def display_content(content)
|
244
|
+
def display_content(content, open_after)
|
245
|
+
puts "\nCurrent Lesson: #{content["title"]}"
|
197
246
|
case content["style"]
|
198
247
|
when "video"
|
199
|
-
|
200
|
-
exec("open video/#{content["s3_key"]}")
|
248
|
+
location = "video/#{content["s3_key"]}"
|
201
249
|
when "quiz"
|
202
250
|
Quiz.start(["give_quiz", "quiz/" + content["s3_key"]])
|
203
251
|
when "lab"
|
204
|
-
|
205
|
-
puts "Lab downloaded to lab/#{content["s3_key"]}, navigate there and look at the README to continue"
|
252
|
+
location = "lab/#{content["s3_key"]}"
|
206
253
|
when "text"
|
207
|
-
|
208
|
-
exec("$EDITOR text/#{content["s3_key"]}")
|
254
|
+
location = "lab/#{content["s3_key"]}"
|
209
255
|
when "cgrp"
|
210
|
-
puts "The Complete Guide to Rails Performance has been downloaded and extracted to the cgrp directory."
|
256
|
+
puts "The Complete Guide to Rails Performance has been downloaded and extracted to the ./cgrp directory."
|
211
257
|
puts "All source code for the CGRP is in the src directory, PDF and other compiled formats are in the release directory."
|
212
258
|
end
|
259
|
+
if location
|
260
|
+
puts "Downloaded to:"
|
261
|
+
puts location.to_s
|
262
|
+
if open_after
|
263
|
+
exec "#{open_command} #{location}"
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
require "rbconfig"
|
269
|
+
def open_command
|
270
|
+
host_os = RbConfig::CONFIG["host_os"]
|
271
|
+
case host_os
|
272
|
+
when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
273
|
+
"start"
|
274
|
+
when /darwin|mac os/
|
275
|
+
"open"
|
276
|
+
else
|
277
|
+
"xdg-open"
|
278
|
+
end
|
213
279
|
end
|
214
280
|
end
|
215
281
|
|
@@ -219,50 +285,72 @@ module RPW
|
|
219
285
|
class ClientData
|
220
286
|
DOTFILE_NAME = ".rpw_info"
|
221
287
|
|
222
|
-
def
|
288
|
+
def initialize
|
223
289
|
make_sure_dotfile_exists
|
290
|
+
data # access file to load
|
291
|
+
end
|
292
|
+
|
293
|
+
def [](key)
|
224
294
|
data[key]
|
225
295
|
end
|
226
296
|
|
227
297
|
def []=(key, value)
|
298
|
+
data
|
228
299
|
data[key] = value
|
300
|
+
|
229
301
|
begin
|
230
|
-
File.open(
|
302
|
+
File.open(filestore_location, "w") { |f| f.write(YAML.dump(data)) }
|
231
303
|
rescue
|
232
|
-
raise Error, "The RPW data
|
304
|
+
raise Error, "The RPW data at #{filestore_location} is not writable. \
|
233
305
|
Check your file permissions."
|
234
306
|
end
|
235
307
|
end
|
236
308
|
|
309
|
+
def self.delete_filestore
|
310
|
+
return unless File.exist?(filestore_location)
|
311
|
+
FileUtils.remove(filestore_location)
|
312
|
+
end
|
313
|
+
|
314
|
+
def self.filestore_location
|
315
|
+
if File.exist?(File.expand_path("./" + self::DOTFILE_NAME))
|
316
|
+
File.expand_path("./" + + self::DOTFILE_NAME)
|
317
|
+
else
|
318
|
+
File.expand_path("~/.rpw/" + self::DOTFILE_NAME)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
237
322
|
private
|
238
323
|
|
324
|
+
def filestore_location
|
325
|
+
self.class.filestore_location
|
326
|
+
end
|
327
|
+
|
328
|
+
def create_client_data_directory(path)
|
329
|
+
dirname = File.dirname(path)
|
330
|
+
FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
|
331
|
+
end
|
332
|
+
|
239
333
|
def data
|
240
334
|
@data ||= begin
|
241
|
-
yaml =
|
242
|
-
YAML.safe_load(File.read(self.class::DOTFILE_NAME))
|
243
|
-
rescue
|
244
|
-
nil
|
245
|
-
end
|
335
|
+
yaml = YAML.safe_load(File.read(filestore_location), permitted_classes: [Time])
|
246
336
|
yaml || {}
|
247
337
|
end
|
248
338
|
end
|
249
339
|
|
250
340
|
def make_sure_dotfile_exists
|
251
|
-
return true if File.exist?(
|
341
|
+
return true if File.exist?(filestore_location)
|
342
|
+
create_client_data_directory(filestore_location)
|
252
343
|
begin
|
253
|
-
FileUtils.touch(
|
344
|
+
FileUtils.touch(filestore_location)
|
254
345
|
rescue
|
255
|
-
raise Error, "Could not create the RPW data file
|
346
|
+
raise Error, "Could not create the RPW data file at ~/.rpw/ \
|
256
347
|
Check your file permissions."
|
257
348
|
end
|
258
349
|
end
|
259
350
|
end
|
260
351
|
|
261
|
-
class Keyfile < ClientData
|
262
|
-
DOTFILE_NAME = ".rpw_key"
|
263
|
-
end
|
264
|
-
|
265
352
|
require "digest"
|
353
|
+
require "thor"
|
266
354
|
|
267
355
|
class Quiz < Thor
|
268
356
|
desc "give_quiz FILENAME", ""
|
@@ -277,13 +365,14 @@ module RPW
|
|
277
365
|
puts data["prompt"]
|
278
366
|
data["answer_choices"].each { |ac| puts ac }
|
279
367
|
provided_answer = ask("Your answer?")
|
280
|
-
answer_digest = Digest::MD5.hexdigest(data["prompt"] + provided_answer)
|
368
|
+
answer_digest = Digest::MD5.hexdigest(data["prompt"] + provided_answer.upcase)
|
281
369
|
if answer_digest == data["answer_digest"]
|
282
370
|
say "Correct!"
|
283
371
|
else
|
284
372
|
say "Incorrect."
|
285
373
|
say "I encourage you to try reviewing the material to see what the correct answer is."
|
286
374
|
end
|
375
|
+
say ""
|
287
376
|
end
|
288
377
|
end
|
289
378
|
end
|
data/lib/rpw/version.rb
CHANGED
data/rpw.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rpw
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nate Berkopec
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-10-
|
11
|
+
date: 2020-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thor-hollaback
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: typhoeus
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|