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.
@@ -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
@@ -1,5 +1,5 @@
1
- $:.unshift File.dirname(__FILE__)
2
- %w[rubygems tempfile fileutils net/http yaml open-uri wrap].each { |f| require f }
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| show(body.read) }
22
+ return open(uri, headers) { |body| process(body.read) }
23
23
  end
24
24
 
25
- return show(File.read(cache_file)) if File.exists?(cache_file) rescue clear_cache if cache_file
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
- File.open(cache_file, 'w') { |f| f.write(sheet) } if try_to_cache && cache_file && !@edit
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
- clear_cache if @edit = args.delete('--edit')
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} --new"
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
- PLATFORM =~ /win32/ ? win32_cache_dir : File.join(File.expand_path("~"), ".cheat")
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,4 +1,3 @@
1
- require 'rubygems'
2
1
  require 'diff/lcs'
3
2
  require 'diff/lcs/hunk'
4
3
 
@@ -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
- require_gem 'camping', '>=1.4.152'
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
- URL = ARGV.include?('debug') ? 'http://localhost:3001' : 'http://cheat.errtheblog.com'
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 :title, :with => /^[a-z]+[a-z0-9_]*$/i
36
- validates_presence_of :title, :body
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.find_by_title(title)
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
- return { 'Recent Cheat Sheets' => Sheet.find(:all, :order => 'created_at DESC', :limit => 15).map(&:title) }.to_yaml
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
- return { 'All Cheat Sheets' => Sheet.find(:all, :order => 'title ASC').map(&:title) }.to_yaml
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.find_by_title(title)
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.ruby-forum.com/captcha/check_answer/#{session}/#{answer}").read.to_i.nonzero? rescue false
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.find(:all, :order => 'title ASC')
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.find_by_title(title)
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.find_by_title(title)
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
- @sheets = Sheet.find_by_title(title).find_versions(:order => 'version DESC')
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 { |s| s.version } }.to_yaml }
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
- a "diff", :href => R(Diff, @sheet.title, diff_version) if diff_version
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.ruby-forum.com/captcha/image/#{random}"
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 "$ sudo gem install cheat"
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.find(:all, :order => 'updated_at DESC', :limit => 20)
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/theme/feed.png")
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
- @current_sheet ||= Cheat::Models::Sheet.find_by_title(@sheet.title)
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.find(:all, :order => 'updated_at DESC', :limit => 15)
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 : return (distance==0) ? 'less than a minute' : '1 minute'
544
- when 2..45 : "#{distance} minutes"
545
- when 46..90 : 'about 1 hour'
546
- when 90..1440 : "about #{(distance.to_f / 60.0).round} hours"
547
- when 1441..2880: '1 day'
548
- else "#{(distance / 1440).round} days"
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", 3001, "/", Cheat)
588
- puts "** Cheat is running at http://0.0.0.0:3001/"
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