cheat 1.2.1 → 1.3.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/README +5 -0
- data/bin/cheat +8 -2
- data/lib/ambition/LICENSE +18 -0
- data/lib/ambition/README +143 -0
- data/lib/ambition/Rakefile +29 -0
- data/lib/ambition/init.rb +1 -0
- data/lib/ambition/lib/ambition.rb +21 -0
- data/lib/ambition/lib/ambition/count.rb +8 -0
- data/lib/ambition/lib/ambition/enumerable.rb +9 -0
- data/lib/ambition/lib/ambition/limit.rb +34 -0
- data/lib/ambition/lib/ambition/order.rb +52 -0
- data/lib/ambition/lib/ambition/processor.rb +54 -0
- data/lib/ambition/lib/ambition/query.rb +85 -0
- data/lib/ambition/lib/ambition/where.rb +164 -0
- data/lib/ambition/lib/proc_to_ruby.rb +36 -0
- data/lib/ambition/test/chaining_test.rb +34 -0
- data/lib/ambition/test/count_test.rb +17 -0
- data/lib/ambition/test/enumerable_test.rb +51 -0
- data/lib/ambition/test/helper.rb +30 -0
- data/lib/ambition/test/join_test.rb +32 -0
- data/lib/ambition/test/limit_test.rb +37 -0
- data/lib/ambition/test/order_test.rb +48 -0
- data/lib/ambition/test/types_test.rb +56 -0
- data/lib/ambition/test/where_test.rb +131 -0
- data/lib/cheat.rb +81 -11
- data/lib/{diffr.rb → cheat/diffr.rb} +0 -1
- data/lib/{responder.rb → cheat/responder.rb} +3 -3
- data/lib/cheat/rv_harness.rb +41 -0
- data/lib/{site.rb → cheat/site.rb} +114 -93
- data/lib/cheat/version.rb +3 -0
- data/lib/{wrap.rb → cheat/wrap.rb} +0 -0
- metadata +77 -42
- data/lib/cheat/commands.rb +0 -41
- data/lib/new_cheat.rb +0 -163
- data/test/test_cheat.rb +0 -50
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
##
|
4
|
+
# Once dynamically, once hardcoded
|
5
|
+
context "Different types" do
|
6
|
+
types_hash = {
|
7
|
+
'string' => "'string'",
|
8
|
+
:symbol => "'--- :symbol\n'",
|
9
|
+
1 => '1',
|
10
|
+
1.2 => '1.2',
|
11
|
+
nil => 'NULL',
|
12
|
+
true => '1',
|
13
|
+
false => '0',
|
14
|
+
Time.now => "'#{Time.now.to_s(:db)}'",
|
15
|
+
DateTime.now => "'#{DateTime.now.to_s(:db)}'",
|
16
|
+
Date.today => "'#{Date.today.to_s(:db)}'"
|
17
|
+
}
|
18
|
+
|
19
|
+
types_hash.each do |type, translation|
|
20
|
+
specify "simple using #{type}" do
|
21
|
+
sql = User.select { |m| m.name == type }.to_sql
|
22
|
+
sql.should == "SELECT * FROM users WHERE users.`name` = #{translation}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
specify "float" do
|
27
|
+
sql = User.select { |m| m.name == 1.2 }.to_sql
|
28
|
+
sql.should == "SELECT * FROM users WHERE users.`name` = 1.2"
|
29
|
+
end
|
30
|
+
|
31
|
+
specify "integer" do
|
32
|
+
sql = User.select { |m| m.name == 1 }.to_sql
|
33
|
+
sql.should == "SELECT * FROM users WHERE users.`name` = 1"
|
34
|
+
end
|
35
|
+
|
36
|
+
specify "true" do
|
37
|
+
sql = User.select { |m| m.name == true }.to_sql
|
38
|
+
sql.should == "SELECT * FROM users WHERE users.`name` = 1"
|
39
|
+
end
|
40
|
+
|
41
|
+
specify "false" do
|
42
|
+
sql = User.select { |m| m.name == false }.to_sql
|
43
|
+
sql.should == "SELECT * FROM users WHERE users.`name` = 0"
|
44
|
+
end
|
45
|
+
|
46
|
+
specify "nil" do
|
47
|
+
sql = User.select { |m| m.name == nil }.to_sql
|
48
|
+
sql.should == "SELECT * FROM users WHERE users.`name` = NULL"
|
49
|
+
end
|
50
|
+
|
51
|
+
xspecify "Time" do
|
52
|
+
# TODO: nothing but variables inside blocks for now
|
53
|
+
sql = User.select { |m| m.name == Time.now }.to_sql
|
54
|
+
sql.should == "SELECT * FROM users WHERE users.`name` = NULL"
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
context "Where (using select)" do
|
4
|
+
specify "simple ==" do
|
5
|
+
sql = User.select { |m| m.name == 'jon' }.to_sql
|
6
|
+
sql.should == "SELECT * FROM users WHERE users.`name` = 'jon'"
|
7
|
+
end
|
8
|
+
|
9
|
+
specify "simple !=" do
|
10
|
+
sql = User.select { |m| m.name != 'jon' }.to_sql
|
11
|
+
sql.should == "SELECT * FROM users WHERE users.`name` <> 'jon'"
|
12
|
+
end
|
13
|
+
|
14
|
+
specify "simple == && ==" do
|
15
|
+
sql = User.select { |m| m.name == 'jon' && m.age == 21 }.to_sql
|
16
|
+
sql.should == "SELECT * FROM users WHERE (users.`name` = 'jon' AND users.`age` = 21)"
|
17
|
+
end
|
18
|
+
|
19
|
+
specify "simple == || ==" do
|
20
|
+
sql = User.select { |m| m.name == 'jon' || m.age == 21 }.to_sql
|
21
|
+
sql.should == "SELECT * FROM users WHERE (users.`name` = 'jon' OR users.`age` = 21)"
|
22
|
+
end
|
23
|
+
|
24
|
+
specify "mixed && and ||" do
|
25
|
+
sql = User.select { |m| m.name == 'jon' || m.age == 21 && m.password == 'pass' }.to_sql
|
26
|
+
sql.should == "SELECT * FROM users WHERE (users.`name` = 'jon' OR (users.`age` = 21 AND users.`password` = 'pass'))"
|
27
|
+
end
|
28
|
+
|
29
|
+
specify "grouped && and ||" do
|
30
|
+
sql = User.select { |m| (m.name == 'jon' || m.name == 'rick') && m.age == 21 }.to_sql
|
31
|
+
sql.should == "SELECT * FROM users WHERE ((users.`name` = 'jon' OR users.`name` = 'rick') AND users.`age` = 21)"
|
32
|
+
end
|
33
|
+
|
34
|
+
specify "simple >/<" do
|
35
|
+
sql = User.select { |m| m.age > 21 }.to_sql
|
36
|
+
sql.should == "SELECT * FROM users WHERE users.`age` > 21"
|
37
|
+
|
38
|
+
sql = User.select { |m| m.age < 21 }.to_sql
|
39
|
+
sql.should == "SELECT * FROM users WHERE users.`age` < 21"
|
40
|
+
end
|
41
|
+
|
42
|
+
specify "array.include? item" do
|
43
|
+
sql = User.select { |m| [1, 2, 3, 4].include? m.id }.to_sql
|
44
|
+
sql.should == "SELECT * FROM users WHERE users.`id` IN (1, 2, 3, 4)"
|
45
|
+
end
|
46
|
+
|
47
|
+
specify "simple == with variables" do
|
48
|
+
me = 'chris'
|
49
|
+
sql = User.select { |m| m.name == me }.to_sql
|
50
|
+
sql.should == "SELECT * FROM users WHERE users.`name` = '#{me}'"
|
51
|
+
end
|
52
|
+
|
53
|
+
specify "simple == with method arguments" do
|
54
|
+
def test_it(name)
|
55
|
+
sql = User.select { |m| m.name == name }.to_sql
|
56
|
+
sql.should == "SELECT * FROM users WHERE users.`name` = '#{name}'"
|
57
|
+
end
|
58
|
+
|
59
|
+
test_it('chris')
|
60
|
+
end
|
61
|
+
|
62
|
+
specify "simple == with instance variables" do
|
63
|
+
@me = 'chris'
|
64
|
+
sql = User.select { |m| m.name == @me }.to_sql
|
65
|
+
sql.should == "SELECT * FROM users WHERE users.`name` = '#{@me}'"
|
66
|
+
end
|
67
|
+
|
68
|
+
xspecify "simple == with instance variable method call" do
|
69
|
+
require 'ostruct'
|
70
|
+
@person = OpenStruct.new(:name => 'chris')
|
71
|
+
|
72
|
+
sql = User.select { |m| m.name == @person.name }.to_sql
|
73
|
+
sql.should == "SELECT * FROM users WHERE users.`name` = '#{@person.name}'"
|
74
|
+
end
|
75
|
+
|
76
|
+
specify "simple == with global variables" do
|
77
|
+
$my_name = 'boston'
|
78
|
+
sql = User.select { |m| m.name == $my_name }.to_sql
|
79
|
+
sql.should == "SELECT * FROM users WHERE users.`name` = '#{$my_name}'"
|
80
|
+
end
|
81
|
+
|
82
|
+
specify "simple == with method call" do
|
83
|
+
def band
|
84
|
+
'megadeth'
|
85
|
+
end
|
86
|
+
|
87
|
+
sql = User.select { |m| m.name == band }.to_sql
|
88
|
+
sql.should == "SELECT * FROM users WHERE users.`name` = '#{band}'"
|
89
|
+
end
|
90
|
+
|
91
|
+
specify "simple =~ with string" do
|
92
|
+
sql = User.select { |m| m.name =~ 'chris' }.to_sql
|
93
|
+
sql.should == "SELECT * FROM users WHERE users.`name` LIKE 'chris'"
|
94
|
+
|
95
|
+
sql = User.select { |m| m.name =~ 'chri%' }.to_sql
|
96
|
+
sql.should == "SELECT * FROM users WHERE users.`name` LIKE 'chri%'"
|
97
|
+
end
|
98
|
+
|
99
|
+
specify "simple !~ with string" do
|
100
|
+
sql = User.select { |m| m.name !~ 'chris' }.to_sql
|
101
|
+
sql.should == "SELECT * FROM users WHERE users.`name` NOT LIKE 'chris'"
|
102
|
+
|
103
|
+
sql = User.select { |m| !(m.name =~ 'chris') }.to_sql
|
104
|
+
sql.should == "SELECT * FROM users WHERE users.`name` NOT LIKE 'chris'"
|
105
|
+
end
|
106
|
+
|
107
|
+
specify "simple =~ with regexp" do
|
108
|
+
sql = User.select { |m| m.name =~ /chris/ }.to_sql
|
109
|
+
sql.should == "SELECT * FROM users WHERE users.`name` REGEXP 'chris'"
|
110
|
+
end
|
111
|
+
|
112
|
+
xspecify "simple == with inline ruby" do
|
113
|
+
# TODO: implement this
|
114
|
+
sql = User.select { |m| m.created_at == 2.days.ago.to_s(:db) }.to_sql
|
115
|
+
sql.should == "SELECT * FROM users WHERE users.`created_at` = #{2.days.ago.to_s(:db)}"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "Where (using detect)" do
|
120
|
+
specify "simple ==" do
|
121
|
+
conditions = { :conditions => "users.`name` = 'chris'", :limit => '1' }
|
122
|
+
User.expects(:find).with(:first, conditions)
|
123
|
+
User.detect { |m| m.name == 'chris' }
|
124
|
+
end
|
125
|
+
|
126
|
+
specify "nothing found" do
|
127
|
+
conditions = { :conditions => "users.`name` = 'chris'", :limit => '1' }
|
128
|
+
User.expects(:find).with(:first, conditions).returns(nil)
|
129
|
+
User.detect { |m| m.name == 'chris' }.should.be.nil
|
130
|
+
end
|
131
|
+
end
|
data/lib/cheat.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
%w( tempfile fileutils net/http yaml open-uri cheat/wrap ).each { |f| require f }
|
2
|
+
RUBY_PLATFORM = PLATFORM unless defined? RUBY_PLATFORM # Ruby 1.8 compatibility
|
3
3
|
|
4
4
|
module Cheat
|
5
5
|
extend self
|
@@ -19,10 +19,10 @@ module Cheat
|
|
19
19
|
|
20
20
|
if %w[sheets all recent].include? @sheet
|
21
21
|
uri = uri.sub('/y/', @sheet == 'recent' ? '/yr/' : '/ya/')
|
22
|
-
return open(uri) { |body|
|
22
|
+
return open(uri, headers) { |body| process(body.read) }
|
23
23
|
end
|
24
24
|
|
25
|
-
return
|
25
|
+
return process(File.read(cache_file)) if File.exists?(cache_file) rescue clear_cache if cache_file
|
26
26
|
|
27
27
|
fetch_sheet(uri + @sheet) if @sheet
|
28
28
|
end
|
@@ -30,7 +30,8 @@ module Cheat
|
|
30
30
|
def fetch_sheet(uri, try_to_cache = true)
|
31
31
|
open(uri, headers) do |body|
|
32
32
|
sheet = body.read
|
33
|
-
|
33
|
+
FileUtils.mkdir_p(cache_dir) unless File.exists?(cache_dir)
|
34
|
+
File.open(cache_file, 'w') { |f| f.write(sheet) } if try_to_cache && has_content(sheet) && cache_file && !@edit
|
34
35
|
@edit ? edit(sheet) : show(sheet)
|
35
36
|
end
|
36
37
|
exit
|
@@ -53,10 +54,12 @@ module Cheat
|
|
53
54
|
show_versions(args.first) if args.delete('--versions')
|
54
55
|
|
55
56
|
add(args.shift) and return if args.delete('--add')
|
56
|
-
|
57
|
-
|
57
|
+
incoming_file = true if @edit = args.delete('--edit')
|
58
|
+
|
59
|
+
@execute = true if args.delete("--execute") || args.delete("-x")
|
58
60
|
@sheet = args.shift
|
59
61
|
|
62
|
+
clear_cache_file if incoming_file
|
60
63
|
true
|
61
64
|
end
|
62
65
|
|
@@ -76,6 +79,13 @@ module Cheat
|
|
76
79
|
fetch_sheet(uri, false)
|
77
80
|
end
|
78
81
|
|
82
|
+
def has_content(sheet)
|
83
|
+
if sheet.is_a?(String)
|
84
|
+
return (sheet.length > 15) && !sheet[0,14].include?("Error!")
|
85
|
+
end
|
86
|
+
return true
|
87
|
+
end
|
88
|
+
|
79
89
|
def cache_file
|
80
90
|
"#{cache_dir}/#{@sheet}.yml" if cache_dir
|
81
91
|
end
|
@@ -83,18 +93,46 @@ module Cheat
|
|
83
93
|
def headers
|
84
94
|
{ 'User-Agent' => 'cheat!', 'Accept' => 'text/yaml' }
|
85
95
|
end
|
86
|
-
|
96
|
+
|
87
97
|
def cheat_uri
|
88
98
|
"#{HOST}:#{PORT}#{SUFFIX}"
|
89
99
|
end
|
90
100
|
|
101
|
+
def execute(sheet_yaml)
|
102
|
+
sheet_body = YAML.load(sheet_yaml).to_a.flatten.last
|
103
|
+
puts "\n " + sheet_body.gsub("\r",'').gsub("\n", "\n ").wrap
|
104
|
+
puts "\nWould you like to execute the above sheet? (Y/N)"
|
105
|
+
answer = STDIN.gets
|
106
|
+
case answer.chomp
|
107
|
+
when "Y" then system YAML.load(sheet_yaml).to_a.flatten.last
|
108
|
+
when "N" then puts "Not executing sheet."
|
109
|
+
else
|
110
|
+
puts "Must be Y or N!"
|
111
|
+
end
|
112
|
+
rescue Errno::EPIPE
|
113
|
+
# do nothing
|
114
|
+
rescue
|
115
|
+
puts "That didn't work. Maybe try `$ cheat cheat' for help?" # Fix Emacs ruby-mode highlighting bug: `"
|
116
|
+
end
|
117
|
+
|
118
|
+
def process(sheet_yaml)
|
119
|
+
if @execute
|
120
|
+
execute(sheet_yaml)
|
121
|
+
else
|
122
|
+
show(sheet_yaml)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
91
126
|
def show(sheet_yaml)
|
92
127
|
sheet = YAML.load(sheet_yaml).to_a.first
|
93
128
|
sheet[-1] = sheet.last.join("\n") if sheet[-1].is_a?(Array)
|
129
|
+
run_pager
|
94
130
|
puts sheet.first + ':'
|
95
131
|
puts ' ' + sheet.last.gsub("\r",'').gsub("\n", "\n ").wrap
|
132
|
+
rescue Errno::EPIPE
|
133
|
+
# do nothing
|
96
134
|
rescue
|
97
|
-
puts "That didn't work. Maybe try `$ cheat cheat' for help?"
|
135
|
+
puts "That didn't work. Maybe try `$ cheat cheat' for help?" # Fix Emacs ruby-mode highlighting bug: `"
|
98
136
|
end
|
99
137
|
|
100
138
|
def edit(sheet_yaml)
|
@@ -138,7 +176,7 @@ module Cheat
|
|
138
176
|
puts "Here's what you wrote, so it isn't lost in the void:"
|
139
177
|
puts text
|
140
178
|
else
|
141
|
-
puts "Success! Try it!", "$ cheat #{title}
|
179
|
+
puts "Success! Try it!", "$ cheat #{title}"
|
142
180
|
end
|
143
181
|
end
|
144
182
|
|
@@ -147,7 +185,7 @@ module Cheat
|
|
147
185
|
end
|
148
186
|
|
149
187
|
def cache_dir
|
150
|
-
|
188
|
+
RUBY_PLATFORM =~ /win32/ ? win32_cache_dir : File.join(File.expand_path("~"), ".cheat")
|
151
189
|
end
|
152
190
|
|
153
191
|
def win32_cache_dir
|
@@ -163,6 +201,38 @@ module Cheat
|
|
163
201
|
def clear_cache
|
164
202
|
FileUtils.rm_rf(cache_dir) if cache_dir
|
165
203
|
end
|
204
|
+
|
205
|
+
def clear_cache_file
|
206
|
+
FileUtils.rm(cache_file) if File.exists?(cache_file)
|
207
|
+
end
|
208
|
+
|
209
|
+
def run_pager
|
210
|
+
return if RUBY_PLATFORM =~ /win32/
|
211
|
+
return unless STDOUT.tty?
|
212
|
+
|
213
|
+
read, write = IO.pipe
|
214
|
+
|
215
|
+
unless Kernel.fork # Child process
|
216
|
+
STDOUT.reopen(write)
|
217
|
+
STDERR.reopen(write) if STDERR.tty?
|
218
|
+
read.close
|
219
|
+
write.close
|
220
|
+
return
|
221
|
+
end
|
222
|
+
|
223
|
+
# Parent process, become pager
|
224
|
+
STDIN.reopen(read)
|
225
|
+
read.close
|
226
|
+
write.close
|
227
|
+
|
228
|
+
ENV['LESS'] = 'FSRX' # Don't page if the input is short enough
|
229
|
+
|
230
|
+
# wait until we have input before we start the pager
|
231
|
+
Kernel.select [STDIN]
|
232
|
+
pager = ENV['PAGER'] || 'less'
|
233
|
+
exec pager rescue exec "/bin/sh", "-c", pager
|
234
|
+
rescue
|
235
|
+
end
|
166
236
|
end
|
167
237
|
|
168
238
|
Cheat.sheets(ARGV) if __FILE__ == $0
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# class Something < R 'route'
|
2
2
|
# include Responder
|
3
|
-
#
|
3
|
+
#
|
4
4
|
# def get
|
5
5
|
# ... important code ...
|
6
6
|
#
|
@@ -24,7 +24,7 @@ module Cheat::Controllers
|
|
24
24
|
attr_reader :body, :content_type
|
25
25
|
def initialize(accept) @accept = accept end
|
26
26
|
|
27
|
-
TYPES = {
|
27
|
+
TYPES = {
|
28
28
|
:yaml => %w[application/yaml text/yaml],
|
29
29
|
:text => %w[text/plain],
|
30
30
|
:html => %w[text/html */* application/html],
|
@@ -33,7 +33,7 @@ module Cheat::Controllers
|
|
33
33
|
|
34
34
|
def method_missing(method, *args)
|
35
35
|
if TYPES[method] && @accept =~ Regexp.union(*TYPES[method])
|
36
|
-
@content_type = TYPES[method].first
|
36
|
+
@content_type = TYPES[method].first
|
37
37
|
@body = yield if block_given?
|
38
38
|
end
|
39
39
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
# Example mongrel harness for camping apps with rv
|
3
|
+
#
|
4
|
+
# author: Evan Weaver
|
5
|
+
# url: http://blog.evanweaver.com/articles/2006/12/19/rv-a-tool-for-luxurious-camping
|
6
|
+
# license: AFL 3.0
|
7
|
+
|
8
|
+
require 'mongrel'
|
9
|
+
require 'mongrel/camping'
|
10
|
+
LOGFILE = 'mongrel.log'
|
11
|
+
PIDFILE = 'mongrel.pid'
|
12
|
+
|
13
|
+
# or whatever else you want passed in
|
14
|
+
PORT = ARGV[0].to_i
|
15
|
+
ADDR = ARGV[1]
|
16
|
+
|
17
|
+
# this is your camping app
|
18
|
+
require 'site'
|
19
|
+
app = Cheat
|
20
|
+
|
21
|
+
# custom database configuration
|
22
|
+
app::Models::Base.establish_connection :adapter => 'mysql', :user => 'root', :database => 'camping', :host => 'localhost'
|
23
|
+
|
24
|
+
app::Models::Base.logger = nil
|
25
|
+
app::Models::Base.threaded_connections = false
|
26
|
+
app.create
|
27
|
+
|
28
|
+
config = Mongrel::Configurator.new :host => ADDR, :pid_file => PIDFILE do
|
29
|
+
listener :port => PORT do
|
30
|
+
uri '/', :handler => Mongrel::Camping::CampingHandler.new(app)
|
31
|
+
# use the mongrel static server in production instead of the camping controller
|
32
|
+
uri '/static/', :handler => Mongrel::DirHandler.new("static/")
|
33
|
+
uri '/favicon.ico', :handler => Mongrel::Error404Handler.new('')
|
34
|
+
setup_signals
|
35
|
+
run
|
36
|
+
write_pid_file
|
37
|
+
log "#{app} available at #{ADDR}:#{PORT}"
|
38
|
+
join
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# According to Wikipedia, Cheat can refer to:
|
3
|
-
# Cheating, to take advantage of a situation by the breaking of accepted rules
|
3
|
+
# Cheating, to take advantage of a situation by the breaking of accepted rules
|
4
4
|
# or standards
|
5
5
|
# Cheating (casino)
|
6
6
|
# Cheating in poker
|
@@ -10,30 +10,38 @@
|
|
10
10
|
# Cheating, parasitic abuse of symbiotic relationships
|
11
11
|
# The Cheat, a character in the cartoon series Homestar Runner
|
12
12
|
# Cheat!, a television show on the G4 network
|
13
|
-
# The Cheat, a 1915 Cecil B. DeMille movie about a wealthy and domineering
|
13
|
+
# The Cheat, a 1915 Cecil B. DeMille movie about a wealthy and domineering
|
14
14
|
# Asian gentleman taking advantage of an American female
|
15
15
|
# Cheats, a 2002 comedy, starring Matthew Lawrence and Mary Tyler Moore
|
16
|
-
# Cheat, a song by The Clash from the UK version of their album The Clash
|
16
|
+
# Cheat, a song by The Clash from the UK version of their album The Clash
|
17
17
|
# Bullshit, sometimes known as "Cheat," a card game
|
18
18
|
# An alternate term for defection in the prisoner's dilemma in game theory
|
19
|
-
# Cheat River, a tributary of the Monongahela River in Appalachia; the Cheat
|
19
|
+
# Cheat River, a tributary of the Monongahela River in Appalachia; the Cheat
|
20
20
|
# starts in West Virginia, and flows westward
|
21
21
|
# Cheat Lake, a nearby resevoir
|
22
22
|
# Cheat Mountain, one of the highest mountains in the Alleghenies
|
23
23
|
#
|
24
|
-
%w[rubygems camping camping/db erb open-uri acts_as_versioned wrap diffr responder].each { |f| require f }
|
25
|
-
|
24
|
+
%w[rubygems camping camping/db erb open-uri acts_as_versioned wrap diffr responder ambition].each { |f| require f }
|
25
|
+
gem 'camping', '>=1.4.152'
|
26
26
|
|
27
27
|
Camping.goes :Cheat
|
28
28
|
|
29
|
-
|
29
|
+
# for defunkt. campistrano.
|
30
|
+
if ARGV.include? '--update'
|
31
|
+
ssh = 'ssh deploy@errtheblog.com'
|
32
|
+
puts `#{ssh} 'cd /var/www/cheat; svn up'`
|
33
|
+
system "#{ssh} 'sudo /etc/init.d/rv restart'"
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
|
37
|
+
URL = ARGV.include?('debug') ? 'http://localhost:8020' : 'http://cheat.errtheblog.com'
|
30
38
|
FEED = 'http://feeds.feedburner.com/cheatsheets' # rss feed
|
31
39
|
|
32
40
|
module Cheat::Models
|
33
41
|
class Sheet < Base
|
34
42
|
validates_uniqueness_of :title
|
35
|
-
validates_format_of
|
36
|
-
validates_presence_of
|
43
|
+
validates_format_of :title, :with => /^[a-z]+[a-z0-9_]*$/i
|
44
|
+
validates_presence_of :title, :body
|
37
45
|
before_save { |r| r.title = r.title.gsub(' ', '_').underscore.downcase }
|
38
46
|
acts_as_versioned
|
39
47
|
end
|
@@ -62,7 +70,7 @@ module Cheat::Controllers
|
|
62
70
|
def get(title)
|
63
71
|
@headers['Content-Type'] = 'text/plain'
|
64
72
|
|
65
|
-
sheet = Sheet.
|
73
|
+
sheet = Sheet.detect { |s| s.title == title }
|
66
74
|
return { 'Error!' => "Cheat sheet `#{title}' not found." }.to_yaml unless sheet
|
67
75
|
|
68
76
|
return { sheet.title => sheet.body }.to_yaml
|
@@ -73,7 +81,8 @@ module Cheat::Controllers
|
|
73
81
|
def get
|
74
82
|
@headers['Content-Type'] = 'text/plain'
|
75
83
|
|
76
|
-
|
84
|
+
sheets = Sheet.sort_by { |s| -s.created_at }.first(15).map(&:title)
|
85
|
+
return { 'Recent Cheat Sheets' => sheets }.to_yaml
|
77
86
|
end
|
78
87
|
end
|
79
88
|
|
@@ -81,7 +90,8 @@ module Cheat::Controllers
|
|
81
90
|
def get
|
82
91
|
@headers['Content-Type'] = 'text/plain'
|
83
92
|
|
84
|
-
|
93
|
+
sheets = Sheet.sort_by(&:title).map(&:title)
|
94
|
+
return { 'All Cheat Sheets' => sheets }.to_yaml
|
85
95
|
end
|
86
96
|
end
|
87
97
|
|
@@ -97,30 +107,30 @@ module Cheat::Controllers
|
|
97
107
|
render :index
|
98
108
|
end
|
99
109
|
end
|
100
|
-
|
110
|
+
|
101
111
|
class Add < R '/a'
|
102
112
|
def get
|
103
113
|
@sheet = Sheet.new
|
104
114
|
render :add
|
105
115
|
end
|
106
116
|
end
|
107
|
-
|
117
|
+
|
108
118
|
class Edit < R '/e/(\w+)/(\d+)', '/e/(\w+)'
|
109
119
|
def get(title, version = nil)
|
110
|
-
@sheet = Sheet.
|
120
|
+
@sheet = Sheet.detect { |s| s.title == title }
|
121
|
+
|
111
122
|
@error = "Cheat sheet not found." unless @sheet
|
112
|
-
unless version.nil? || version == @sheet.version.to_s
|
123
|
+
unless version.nil? || version == @sheet.version.to_s
|
113
124
|
@sheet = @sheet.find_version(version)
|
114
125
|
end
|
115
126
|
render @error ? :error : :edit
|
116
127
|
end
|
117
128
|
end
|
118
|
-
|
129
|
+
|
119
130
|
class Write < R '/w', '/w/(\w+)'
|
120
131
|
def post(title = nil)
|
121
132
|
@sheet = title ? Sheet.find_by_title(title) : Sheet.new
|
122
|
-
|
123
|
-
@error = input.sheet_body =~ /<a\s*href=/
|
133
|
+
@sheet = title ? Sheet.detect { |s| s.title == title } : Sheet.new
|
124
134
|
|
125
135
|
check_captcha! unless input.from_gem
|
126
136
|
|
@@ -137,21 +147,21 @@ module Cheat::Controllers
|
|
137
147
|
end
|
138
148
|
|
139
149
|
def captcha_pass?(session, answer)
|
140
|
-
open("http://captchator.
|
150
|
+
open("http://captchator.com/captcha/check_answer/#{session}/#{answer}").read.to_i.nonzero? rescue false
|
141
151
|
end
|
142
152
|
end
|
143
|
-
|
153
|
+
|
144
154
|
class Browse < R '/b'
|
145
155
|
def get
|
146
|
-
@sheets = Sheet.
|
156
|
+
@sheets = Sheet.sort_by(&:title)
|
147
157
|
render :browse
|
148
158
|
end
|
149
159
|
end
|
150
|
-
|
160
|
+
|
151
161
|
class Show < R '/s/(\w+)', '/s/(\w+)/(\d+)'
|
152
162
|
def get(title, version = nil)
|
153
|
-
@sheet = Sheet.
|
154
|
-
@sheet = @sheet.find_version(version) if version && @sheet
|
163
|
+
@sheet = Sheet.detect { |s| s.title == title }
|
164
|
+
@sheet = @sheet.find_version(version) if version && @sheet
|
155
165
|
|
156
166
|
@sheet ? render(:show) : redirect("#{URL}/b/")
|
157
167
|
end
|
@@ -165,7 +175,7 @@ module Cheat::Controllers
|
|
165
175
|
def get(title, old_version, new_version = nil)
|
166
176
|
redirect "#{URL}/b/" and return unless old_version.to_i.nonzero?
|
167
177
|
|
168
|
-
@sheet = Sheet.
|
178
|
+
@sheet = Sheet.detect { |s| s.title == title }
|
169
179
|
@old_sheet = @sheet.find_version(old_version)
|
170
180
|
@new_sheet = (new_version ? @sheet.find_version(new_version) : @sheet)
|
171
181
|
|
@@ -182,11 +192,13 @@ module Cheat::Controllers
|
|
182
192
|
include Responder
|
183
193
|
|
184
194
|
def get(title)
|
185
|
-
|
195
|
+
if sheets = Sheet.detect { |s| s.title == title }
|
196
|
+
@sheets = sheets.find_versions(:order => 'version DESC')
|
197
|
+
end
|
186
198
|
|
187
199
|
respond_to do |wants|
|
188
200
|
wants.html { render :history }
|
189
|
-
wants.yaml { { @sheets.first.title => @sheets.map
|
201
|
+
wants.yaml { { @sheets.first.title => @sheets.map(&:version) }.to_yaml }
|
190
202
|
end
|
191
203
|
end
|
192
204
|
end
|
@@ -202,26 +214,31 @@ module Cheat::Views
|
|
202
214
|
}
|
203
215
|
body {
|
204
216
|
div.main {
|
205
|
-
div.header {
|
206
|
-
h1 { logo_link 'cheat sheets.' }
|
217
|
+
div.header {
|
218
|
+
h1 { logo_link 'cheat sheets.' }
|
207
219
|
code.header @sheet_title ? "$ cheat #{@sheet_title}" : "$ command line ruby cheat sheets"
|
208
220
|
}
|
209
|
-
div.content { self << yield }
|
221
|
+
div.content { self << yield }
|
210
222
|
div.side { _side }
|
211
|
-
div.clear { '' }
|
223
|
+
div.clear { '' }
|
212
224
|
div.footer { _footer }
|
213
225
|
}
|
226
|
+
_clicky
|
214
227
|
}
|
215
228
|
}
|
216
229
|
end
|
217
|
-
|
230
|
+
|
231
|
+
def _clicky
|
232
|
+
text '<script src="http://getclicky.com/1070.js"> </script><noscript><img height=0 width=0 src="http://getclicky.com/1070ns.gif"></noscript>'
|
233
|
+
end
|
234
|
+
|
218
235
|
def error
|
219
236
|
@page_title = "error"
|
220
237
|
p "An error:"
|
221
238
|
code.version @error
|
222
239
|
p ":("
|
223
240
|
end
|
224
|
-
|
241
|
+
|
225
242
|
def show
|
226
243
|
@page_title = @sheet.title
|
227
244
|
@sheet_title = @sheet.title
|
@@ -236,27 +253,29 @@ module Cheat::Views
|
|
236
253
|
text ". o 0 ( "
|
237
254
|
if @sheet.version == current_sheet.version
|
238
255
|
a "edit", :href => R(Edit, @sheet.title)
|
239
|
-
text " | "
|
240
256
|
end
|
241
257
|
if @sheet.version > 1
|
242
|
-
a "previous", :href => R(Show, @sheet.title, @sheet.version - 1)
|
243
258
|
text " | "
|
259
|
+
a "previous", :href => R(Show, @sheet.title, @sheet.version - 1)
|
244
260
|
end
|
261
|
+
text " | "
|
245
262
|
a "history", :href => R(History, @sheet.title)
|
246
|
-
text " | "
|
247
263
|
unless @sheet.version == current_sheet.version
|
264
|
+
text " | "
|
248
265
|
a "revert to", :href => R(Edit, @sheet.title, @sheet.version)
|
249
|
-
text " | "
|
250
|
-
a "current", :href => R(Show, @sheet.title)
|
251
266
|
text " | "
|
267
|
+
a "current", :href => R(Show, @sheet.title)
|
252
268
|
end
|
253
|
-
diff_version =
|
254
|
-
if @sheet.version == current_sheet.version
|
269
|
+
diff_version =
|
270
|
+
if @sheet.version == current_sheet.version
|
255
271
|
@sheet.version == 1 ? nil : @sheet.version - 1
|
256
272
|
else
|
257
273
|
@sheet.version
|
258
274
|
end
|
259
|
-
|
275
|
+
if diff_version
|
276
|
+
text " | "
|
277
|
+
a "diff", :href => R(Diff, @sheet.title, diff_version)
|
278
|
+
end
|
260
279
|
text " )"
|
261
280
|
}
|
262
281
|
end
|
@@ -264,7 +283,7 @@ module Cheat::Views
|
|
264
283
|
def diff
|
265
284
|
@page_title = @sheet.title
|
266
285
|
@sheet_title = @sheet.title
|
267
|
-
pre.sheet { color_diff(@diffed) if @diffed }
|
286
|
+
pre.sheet { color_diff(h(@diffed)) if @diffed }
|
268
287
|
div.version {
|
269
288
|
text ". o 0 ("
|
270
289
|
if @old_sheet.version > 1
|
@@ -277,9 +296,10 @@ module Cheat::Views
|
|
277
296
|
text " )"
|
278
297
|
}
|
279
298
|
end
|
280
|
-
|
299
|
+
|
281
300
|
def browse
|
282
301
|
@page_title = "browse"
|
302
|
+
p { "Wowzers, we've got <strong>#{@sheets.size}</strong> cheat sheets hereabouts." }
|
283
303
|
ul {
|
284
304
|
@sheets.each do |sheet|
|
285
305
|
li { sheet_link sheet.title }
|
@@ -298,7 +318,7 @@ module Cheat::Views
|
|
298
318
|
h2 @sheets.first.title
|
299
319
|
ul {
|
300
320
|
@sheets.each_with_index do |sheet, i|
|
301
|
-
li {
|
321
|
+
li {
|
302
322
|
a "version #{sheet.version}", :href => R(Show, sheet.title, sheet.version)
|
303
323
|
text " - created "
|
304
324
|
text last_updated(sheet)
|
@@ -310,7 +330,7 @@ module Cheat::Views
|
|
310
330
|
end
|
311
331
|
}
|
312
332
|
end
|
313
|
-
|
333
|
+
|
314
334
|
def add
|
315
335
|
@page_title = "add"
|
316
336
|
p {
|
@@ -321,26 +341,26 @@ module Cheat::Views
|
|
321
341
|
}
|
322
342
|
_form
|
323
343
|
end
|
324
|
-
|
344
|
+
|
325
345
|
def edit
|
326
346
|
@page_title = "edit"
|
327
347
|
_form
|
328
348
|
end
|
329
|
-
|
349
|
+
|
330
350
|
def _form
|
331
351
|
if @error
|
332
352
|
p.error {
|
333
353
|
strong "HEY! "
|
334
|
-
text "Something is wrong! You can't give your cheat sheet the same name
|
335
|
-
as another, alphanumeric titles only, and you need to make sure
|
354
|
+
text "Something is wrong! You can't give your cheat sheet the same name
|
355
|
+
as another, alphanumeric titles only, and you need to make sure
|
336
356
|
you filled in all (two) of the fields. Okay?"
|
337
357
|
}
|
338
358
|
end
|
339
359
|
form :method => 'post', :action => R(Write, @sheet.title) do
|
340
360
|
p {
|
341
|
-
p {
|
361
|
+
p {
|
342
362
|
text 'Cheat Sheet Title: '
|
343
|
-
input :value => @sheet.title, :name => 'sheet_title', :size => 30,
|
363
|
+
input :value => @sheet.title, :name => 'sheet_title', :size => 30,
|
344
364
|
:type => 'text'
|
345
365
|
small " [ no_spaces_alphanumeric_only ]"
|
346
366
|
}
|
@@ -351,13 +371,13 @@ module Cheat::Views
|
|
351
371
|
unless @cookies[:passed]
|
352
372
|
random = rand(10_000)
|
353
373
|
br
|
354
|
-
img :src => "http://captchator.
|
374
|
+
img :src => "http://captchator.com/captcha/image/#{random}"
|
355
375
|
input :name => 'chunky', :type => 'hidden', :value => random
|
356
376
|
input :name => 'bacon', :size => 10, :type => 'text'
|
357
377
|
end
|
358
378
|
}
|
359
379
|
}
|
360
|
-
p "Your cheat sheet will be editable (fixable) by anyone. Each cheat
|
380
|
+
p "Your cheat sheet will be editable (fixable) by anyone. Each cheat
|
361
381
|
sheet is essentially a wiki page. It may also be used by millions of
|
362
382
|
people for reference purposes from the comfort of their command line.
|
363
383
|
If this is okay with you, please save."
|
@@ -369,22 +389,22 @@ module Cheat::Views
|
|
369
389
|
p {
|
370
390
|
text "Welcome. You've reached the central repository for "
|
371
391
|
strong "cheat"
|
372
|
-
text ", the RubyGem which puts Ruby-centric cheat sheets right into your
|
392
|
+
text ", the RubyGem which puts Ruby-centric cheat sheets right into your
|
373
393
|
terminal. The inaugural blog entry "
|
374
394
|
a "is here", :href => "http://errtheblog.com/post/23"
|
375
395
|
text "."
|
376
396
|
}
|
377
397
|
p "Get started:"
|
378
|
-
code "$
|
398
|
+
code "$ gem install cheat"
|
379
399
|
br
|
380
400
|
code "$ cheat strftime"
|
381
|
-
p "A magnificent cheat sheet for Ruby's strftime method will be printed to
|
401
|
+
p "A magnificent cheat sheet for Ruby's strftime method will be printed to
|
382
402
|
your terminal."
|
383
403
|
p "To get some help on cheat itself:"
|
384
404
|
code "$ cheat cheat"
|
385
405
|
p "How meta."
|
386
406
|
p {
|
387
|
-
text "Cheat sheets are basically wiki pages accessible from the command
|
407
|
+
text "Cheat sheets are basically wiki pages accessible from the command
|
388
408
|
line. You can "
|
389
409
|
a 'browse', :href => R(Browse)
|
390
410
|
text ', '
|
@@ -393,13 +413,13 @@ module Cheat::Views
|
|
393
413
|
a 'edit', :href => R(Edit, 'cheat')
|
394
414
|
text ' cheat sheets. Try to keep them concise. For a style guide, check
|
395
415
|
out the '
|
396
|
-
a 'cheat', :href => R(Edit, 'cheat')
|
416
|
+
a 'cheat', :href => R(Edit, 'cheat')
|
397
417
|
text ' cheat sheet.'
|
398
418
|
}
|
399
|
-
p "To access a cheat sheet, simply pass the program the desired sheet's
|
419
|
+
p "To access a cheat sheet, simply pass the program the desired sheet's
|
400
420
|
name:"
|
401
421
|
code "$ cheat <sheet name>"
|
402
|
-
p
|
422
|
+
p
|
403
423
|
end
|
404
424
|
|
405
425
|
def self.feed
|
@@ -412,7 +432,7 @@ module Cheat::Views
|
|
412
432
|
xml.id URL + '/'
|
413
433
|
xml.link "rel" => "self", "href" => FEED
|
414
434
|
|
415
|
-
sheets = Cheat::Models::Sheet.
|
435
|
+
sheets = Cheat::Models::Sheet.sort_by { |s| -s.updated_at }.first(20)
|
416
436
|
xml.updated sheets.first.updated_at.xmlschema
|
417
437
|
|
418
438
|
sheets.each do |sheet|
|
@@ -423,14 +443,14 @@ module Cheat::Views
|
|
423
443
|
xml.updated sheet.updated_at.xmlschema
|
424
444
|
xml.link "rel" => "alternate", "href" => URL + '/s/' + sheet.title
|
425
445
|
xml.summary "A cheat sheet about #{sheet.title}. Run it: `$ cheat #{sheet.title}'"
|
426
|
-
xml.content 'type' => 'html' do
|
427
|
-
xml.text! sheet.body.gsub("\n", '<br/>').gsub("\r", '')
|
446
|
+
xml.content 'type' => 'html' do
|
447
|
+
xml.text! sheet.body.gsub("\n", '<br/>').gsub("\r", '')
|
428
448
|
end
|
429
449
|
end
|
430
|
-
end
|
450
|
+
end
|
431
451
|
end
|
432
452
|
end
|
433
|
-
|
453
|
+
|
434
454
|
def _side
|
435
455
|
text '( '
|
436
456
|
a 'add new', :href => R(Add)
|
@@ -441,7 +461,7 @@ module Cheat::Views
|
|
441
461
|
li { strong "updated sheets" }
|
442
462
|
li do
|
443
463
|
a :href => FEED do
|
444
|
-
img(:border => 0, :alt => "Recently Updated Cheat Sheets Feed", :src => "http://errtheblog.com/images/
|
464
|
+
img(:border => 0, :alt => "Recently Updated Cheat Sheets Feed", :src => "http://errtheblog.com/images/feed.png")
|
445
465
|
end
|
446
466
|
end
|
447
467
|
recent_sheets.each do |sheet|
|
@@ -449,13 +469,13 @@ module Cheat::Views
|
|
449
469
|
end
|
450
470
|
}
|
451
471
|
end
|
452
|
-
|
472
|
+
|
453
473
|
def _footer
|
454
474
|
text "Powered by "
|
455
475
|
a 'Camping', :href => "http://code.whytheluckystiff.net/camping"
|
456
476
|
text ", "
|
457
|
-
a 'Mongrel', :href => "http://mongrel.rubyforge.org/"
|
458
|
-
text " and, to a lesser extent, "
|
477
|
+
a 'Mongrel', :href => "http://mongrel.rubyforge.org/"
|
478
|
+
text " and, to a lesser extent, "
|
459
479
|
a 'Err the Blog', :href => "http://errtheblog.com/"
|
460
480
|
text "."
|
461
481
|
end
|
@@ -465,24 +485,24 @@ module Cheat::Views
|
|
465
485
|
h1 = "#4fa3da"
|
466
486
|
link = h1
|
467
487
|
hover = "#f65077"
|
468
|
-
dash = hover
|
488
|
+
dash = hover
|
469
489
|
version = "#fcf095"
|
470
490
|
style :type => "text/css" do
|
471
491
|
text %[
|
472
492
|
body { font-family: verdana, sans-serif; background-color: #{bg};
|
473
493
|
line-height: 20px; }
|
474
|
-
a:link, a:visited { color: #{link}; }
|
494
|
+
a:link, a:visited { color: #{link}; }
|
475
495
|
a:hover { text-decoration: none; color: #{hover}; }
|
476
|
-
div.header { border-bottom: 1px dashed #{dash}; }
|
477
|
-
code.header { margin-left: 30px; font-weight: bold;
|
478
|
-
background-color: #{version}; }
|
479
|
-
h1 { font-size: 5em; margin: 0; padding-left: 30px; color: #{h1};
|
496
|
+
div.header { border-bottom: 1px dashed #{dash}; }
|
497
|
+
code.header { margin-left: 30px; font-weight: bold;
|
498
|
+
background-color: #{version}; }
|
499
|
+
h1 { font-size: 5em; margin: 0; padding-left: 30px; color: #{h1};
|
480
500
|
clear: both; font-weight: bold; letter-spacing: -5px; }
|
481
501
|
h1 a { text-decoration: none; }
|
482
502
|
div.main { float: left; width: 100%; }
|
483
503
|
div.content { float: left; width: 70%; padding: 15px 0 15px 30px;
|
484
504
|
line-height: 20px; }
|
485
|
-
div.side { float: left; padding: 10px; text-align: right;
|
505
|
+
div.side { float: left; padding: 10px; text-align: right;
|
486
506
|
width: 20%; }
|
487
507
|
div.footer { text-align: center; border-top: 1px dashed #{dash};
|
488
508
|
padding-top: 10px; font-size: small; }
|
@@ -490,9 +510,9 @@ module Cheat::Views
|
|
490
510
|
font-family: courier, fixed-width; background-color: #e8e8e8; }
|
491
511
|
pre.sheet { line-height: 15px; }
|
492
512
|
li { list-style: none; }
|
493
|
-
div.version { background-color: #{version}; padding: 5px;
|
513
|
+
div.version { background-color: #{version}; padding: 5px;
|
494
514
|
width: 450px; margin-top: 50px; }
|
495
|
-
p.error { background-color: #{version}; padding: 5px; }
|
515
|
+
p.error { background-color: #{version}; padding: 5px; }
|
496
516
|
div.clear { clear: both; }
|
497
517
|
div.clear_10 { clear: both; font-size: 10px; line-height: 10px; }
|
498
518
|
textarea { font-family: courier; }
|
@@ -520,19 +540,20 @@ module Cheat::Helpers
|
|
520
540
|
a title, :href => R(ctr::Index)
|
521
541
|
end
|
522
542
|
end
|
523
|
-
|
543
|
+
|
524
544
|
def current_sheet
|
525
|
-
|
545
|
+
title = @sheet.title
|
546
|
+
@current_sheet ||= Cheat::Models::Sheet.detect { |s| s.title == title }
|
526
547
|
end
|
527
|
-
|
548
|
+
|
528
549
|
def recent_sheets
|
529
|
-
Cheat::Models::Sheet.
|
550
|
+
Cheat::Models::Sheet.sort_by { |s| -s.updated_at }.first(15)
|
530
551
|
end
|
531
|
-
|
552
|
+
|
532
553
|
def sheet_link(title, version = nil)
|
533
554
|
a title, :href => R(Cheat::Controllers::Show, title, version)
|
534
555
|
end
|
535
|
-
|
556
|
+
|
536
557
|
def last_updated(sheet)
|
537
558
|
from = sheet.updated_at.to_i
|
538
559
|
to = Time.now.to_i
|
@@ -540,12 +561,12 @@ module Cheat::Helpers
|
|
540
561
|
to = to.to_time if to.respond_to?(:to_time)
|
541
562
|
distance = (((to - from).abs)/60).round
|
542
563
|
case distance
|
543
|
-
when 0..1
|
544
|
-
when 2..45
|
545
|
-
when 46..90
|
546
|
-
when 90..1440
|
547
|
-
when 1441..2880
|
548
|
-
else
|
564
|
+
when 0..1 then return (distance==0) ? 'less than a minute' : '1 minute'
|
565
|
+
when 2..45 then "#{distance} minutes"
|
566
|
+
when 46..90 then 'about 1 hour'
|
567
|
+
when 90..1440 then "about #{(distance.to_f / 60.0).round} hours"
|
568
|
+
when 1441..2880 then '1 day'
|
569
|
+
else "#{(distance / 1440).round} days"
|
549
570
|
end
|
550
571
|
end
|
551
572
|
|
@@ -584,7 +605,7 @@ if __FILE__ == $0
|
|
584
605
|
Cheat::Models::Base.threaded_connections = false
|
585
606
|
Cheat.create
|
586
607
|
|
587
|
-
server = Mongrel::Camping.start("0.0.0.0",
|
588
|
-
puts "** Cheat is running at http://0.0.0.0:
|
608
|
+
server = Mongrel::Camping.start("0.0.0.0", 8020, "/", Cheat)
|
609
|
+
puts "** Cheat is running at http://0.0.0.0:8020/"
|
589
610
|
server.run.join
|
590
611
|
end
|