camping 2.0 → 2.1
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/CHANGELOG +11 -0
- data/Rakefile +21 -3
- data/bin/camping +2 -85
- data/book/51_upgrading +17 -0
- data/lib/camping-unabridged.rb +56 -16
- data/lib/camping.rb +37 -32
- data/lib/camping/mab.rb +2 -0
- data/lib/camping/reloader.rb +39 -45
- data/lib/camping/server.rb +217 -130
- data/lib/camping/session.rb +5 -6
- data/lib/camping/template.rb +17 -0
- data/test/app_markup.rb +51 -0
- data/test/app_route_generating.rb +22 -0
- data/test/app_sessions.rb +46 -0
- data/test/app_simple.rb +97 -0
- data/test/test_helper.rb +51 -0
- metadata +9 -16
- data/doc/api.html +0 -1953
- data/doc/book.html +0 -73
- data/doc/book/01_introduction.html +0 -57
- data/doc/book/02_getting_started.html +0 -573
- data/doc/book/51_upgrading.html +0 -146
- data/doc/created.rid +0 -1
- data/doc/images/Camping.gif +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/permalink.gif +0 -0
- data/doc/index.html +0 -148
- data/doc/js/camping.js +0 -79
- data/doc/js/jquery.js +0 -32
- data/doc/rdoc.css +0 -117
data/CHANGELOG
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
= 2.1
|
2
|
+
=== 19th Aug, 2010 (whyday)
|
3
|
+
* Helpers#R now calls to_param on any object it passes in
|
4
|
+
* Fix route generation issue with routes including "." (#22)
|
5
|
+
* Improved tests
|
6
|
+
* Improved 1.9 support
|
7
|
+
* Camping::Server is now built upon Rack::Server
|
8
|
+
* Add support for ERB, Haml etc through Tilt
|
9
|
+
* Introducing Camping.options and Camping#set
|
10
|
+
* Camping::Server only loads ActiveRecord when needed
|
11
|
+
|
1
12
|
= 2.0
|
2
13
|
=== 9th Apr, 2010
|
3
14
|
* Speed-up of Camping::Mab (thanks zimbatm!)
|
data/Rakefile
CHANGED
@@ -10,7 +10,7 @@ task :default => :check
|
|
10
10
|
|
11
11
|
## Constants
|
12
12
|
NAME = "camping"
|
13
|
-
BRANCH = "2.
|
13
|
+
BRANCH = "2.1"
|
14
14
|
GIT = ENV['GIT'] || "git"
|
15
15
|
REV = `#{GIT} rev-list HEAD`.strip.split.length
|
16
16
|
VERS = ENV['VERSION'] || (REV.zero? ? BRANCH : [BRANCH, REV] * '.')
|
@@ -60,6 +60,7 @@ omni =
|
|
60
60
|
s.add_dependency('sqlite3-ruby', '>=1.1.0.1')
|
61
61
|
s.add_dependency('mongrel')
|
62
62
|
s.add_dependency('RedCloth')
|
63
|
+
s.add_dependency('markaby')
|
63
64
|
end
|
64
65
|
|
65
66
|
## RDoc
|
@@ -123,7 +124,8 @@ end
|
|
123
124
|
|
124
125
|
## Tests
|
125
126
|
Rake::TestTask.new(:test) do |t|
|
126
|
-
t.
|
127
|
+
t.libs << "test"
|
128
|
+
t.test_files = FileList['test/app_*.rb']
|
127
129
|
# t.warning = true
|
128
130
|
# t.verbose = true
|
129
131
|
end
|
@@ -139,14 +141,19 @@ task :diff do
|
|
139
141
|
u << Ruby2Ruby.new.process(RubyParser.new.parse(File.read("lib/camping.rb")))
|
140
142
|
m << Ruby2Ruby.new.process(RubyParser.new.parse(File.read("lib/camping-unabridged.rb")))
|
141
143
|
|
144
|
+
u.flush
|
145
|
+
m.flush
|
146
|
+
|
142
147
|
sh "diff -u #{u.path} #{m.path} | less"
|
143
148
|
|
144
149
|
u.delete
|
145
150
|
m.delete
|
146
151
|
end
|
147
152
|
|
153
|
+
error = false
|
154
|
+
|
148
155
|
## Check
|
149
|
-
task :check => ["check:valid", "check:size", "check:lines"]
|
156
|
+
task :check => ["test", "check:valid", "check:size", "check:lines", "check:exit"]
|
150
157
|
namespace :check do
|
151
158
|
|
152
159
|
desc "Check source code validity"
|
@@ -155,8 +162,13 @@ namespace :check do
|
|
155
162
|
u = RubyParser.new.parse(File.read("lib/camping-unabridged.rb"))
|
156
163
|
m = RubyParser.new.parse(File.read("lib/camping.rb"))
|
157
164
|
|
165
|
+
u.reject! do |sexp|
|
166
|
+
sexp.is_a?(Sexp) and sexp[1] == s(:gvar, :$LOADED_FEATURES)
|
167
|
+
end
|
168
|
+
|
158
169
|
unless u == m
|
159
170
|
STDERR.puts "camping.rb and camping-unabridged.rb are not synchronized."
|
171
|
+
error = true
|
160
172
|
end
|
161
173
|
end
|
162
174
|
|
@@ -169,6 +181,7 @@ namespace :check do
|
|
169
181
|
end
|
170
182
|
if File.size("lib/camping.rb") > SIZE_LIMIT
|
171
183
|
STDERR.puts "lib/camping.rb: file is too big (> #{SIZE_LIMIT})"
|
184
|
+
error = true
|
172
185
|
end
|
173
186
|
end
|
174
187
|
|
@@ -177,10 +190,15 @@ namespace :check do
|
|
177
190
|
i = 1
|
178
191
|
File.open("lib/camping.rb").each_line do |line|
|
179
192
|
if line.size > 81 # 1 added for \n
|
193
|
+
error = true
|
180
194
|
STDERR.puts "lib/camping.rb:#{i}: line too long (#{line[-10..-1].inspect})"
|
181
195
|
end
|
182
196
|
i += 1
|
183
197
|
end
|
184
198
|
end
|
199
|
+
|
200
|
+
task :exit do
|
201
|
+
exit 1 if error
|
202
|
+
end
|
185
203
|
|
186
204
|
end
|
data/bin/camping
CHANGED
@@ -1,97 +1,14 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
trap("INT") { exit }
|
4
|
-
require 'optparse'
|
5
|
-
require 'ostruct'
|
6
|
-
require 'stringio'
|
7
|
-
require 'yaml'
|
8
|
-
|
9
3
|
$:.unshift File.dirname(__FILE__) + "/../lib"
|
4
|
+
|
10
5
|
require 'camping'
|
11
6
|
require 'camping/server'
|
12
7
|
|
13
|
-
conf = OpenStruct.new(:host => '0.0.0.0', :port => 3301)
|
14
|
-
|
15
|
-
# Setup paths
|
16
|
-
if home = ENV['HOME'] # POSIX
|
17
|
-
db_path = File.join(home, '.camping.db')
|
18
|
-
rc_path = File.join(home, '.campingrc')
|
19
|
-
elsif home = ENV['APPDATA'] # MSWIN
|
20
|
-
db_path = File.join(home, 'Camping.db')
|
21
|
-
rc_path = File.join(home, 'Campingrc')
|
22
|
-
end
|
23
|
-
|
24
|
-
# Parse options
|
25
|
-
opts = OptionParser.new do |opts|
|
26
|
-
opts.banner = "Usage: camping app1.rb, app2.rb..."
|
27
|
-
opts.define_head "#{File.basename($0)}, the microframework ON-button for ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
|
28
|
-
opts.separator ""
|
29
|
-
opts.separator "Specific options:"
|
30
|
-
|
31
|
-
opts.on("-h", "--host HOSTNAME", "Host for web server to bind to (default is all IPs)") { |val| conf.host = val }
|
32
|
-
opts.on("-p", "--port NUM", "Port for web server (defaults to #{conf.port})") { |val| conf.port = val }
|
33
|
-
opts.on("-d", "--database FILE", "SQLite3 database path (defaults to #{db_path ? db_path : '<none>'})") { |db_path| conf.database = {:adapter => 'sqlite3', :database => db_path} }
|
34
|
-
opts.on("-C", "--console", "Run in console mode with IRB") { conf.server = "console" }
|
35
|
-
server_list = ["mongrel", "webrick", "console"]
|
36
|
-
opts.on("-s", "--server NAME", server_list, "Server to force (#{server_list.join(', ')})") { |val| conf.server = val }
|
37
|
-
|
38
|
-
opts.separator ""
|
39
|
-
opts.separator "Common options:"
|
40
|
-
|
41
|
-
# No argument, shows at tail. This will print an options summary.
|
42
|
-
# Try it and see!
|
43
|
-
opts.on_tail("-?", "--help", "Show this message") do
|
44
|
-
puts opts
|
45
|
-
exit
|
46
|
-
end
|
47
|
-
|
48
|
-
# Another typical switch to print the version.
|
49
|
-
opts.on_tail("-v", "--version", "Show version") do
|
50
|
-
puts Gem.loaded_specs['camping'].version
|
51
|
-
exit
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
8
|
begin
|
56
|
-
|
9
|
+
Camping::Server.start
|
57
10
|
rescue OptionParser::ParseError => ex
|
58
11
|
STDERR.puts "!! #{ex.message}"
|
59
12
|
puts "** use `#{File.basename($0)} --help` for more details..."
|
60
13
|
exit 1
|
61
14
|
end
|
62
|
-
|
63
|
-
if ARGV.length < 1
|
64
|
-
puts opts
|
65
|
-
exit 1
|
66
|
-
end
|
67
|
-
|
68
|
-
# Load configuration if any
|
69
|
-
if rc_path and File.exists?(rc_path)
|
70
|
-
YAML.load_file(rc_path).each do |k,v|
|
71
|
-
conf.send("#{k}=", v) unless conf.send(k)
|
72
|
-
end
|
73
|
-
puts "** conf file #{rc_path} loaded"
|
74
|
-
end
|
75
|
-
|
76
|
-
# Default db
|
77
|
-
if conf.database.nil? and db_path
|
78
|
-
conf.database = { :adapter => 'sqlite3', :database => db_path }
|
79
|
-
end
|
80
|
-
|
81
|
-
|
82
|
-
# get a copy of the paths to pass to the server
|
83
|
-
paths = ARGV.dup
|
84
|
-
|
85
|
-
# Check that mongrel exists
|
86
|
-
if conf.server.nil? || conf.server == "mongrel"
|
87
|
-
begin
|
88
|
-
require 'mongrel'
|
89
|
-
conf.server = "mongrel"
|
90
|
-
rescue LoadError
|
91
|
-
puts "!! Could not load mongrel. Falling back to webrick."
|
92
|
-
conf.server = "webrick"
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
server = Camping::Server.new(conf, paths)
|
97
|
-
server.start
|
data/book/51_upgrading
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
= Appendix I: Upgrade Notes
|
2
2
|
|
3
|
+
This document includes everything needed in order to *upgrade* your
|
4
|
+
applications. If you're looking for all the new features in a version, please
|
5
|
+
have a look at the CHANGELOG in the Camping source.
|
6
|
+
|
7
|
+
|
8
|
+
== From 2.0 to 2.1
|
9
|
+
=== Options
|
10
|
+
|
11
|
+
In Camping 2.1 there is now a built-in way to store options and settings. If
|
12
|
+
you use cookie session, it means that you'll now have to change to:
|
13
|
+
|
14
|
+
module Nuts
|
15
|
+
set :secret, "Very secret text, which no-one else should know!"
|
16
|
+
include Camping::Session
|
17
|
+
end
|
18
|
+
|
19
|
+
|
3
20
|
== From 1.5 to 2.0
|
4
21
|
=== Rack
|
5
22
|
|
data/lib/camping-unabridged.rb
CHANGED
@@ -12,6 +12,8 @@
|
|
12
12
|
require "uri"
|
13
13
|
require "rack"
|
14
14
|
|
15
|
+
$LOADED_FEATURES << "camping.rb"
|
16
|
+
|
15
17
|
class Object #:nodoc:
|
16
18
|
def meta_def(m,&b) #:nodoc:
|
17
19
|
(class<<self;self end).send(:define_method,m,&b)
|
@@ -46,6 +48,7 @@ module Camping
|
|
46
48
|
S = IO.read(__FILE__) rescue nil
|
47
49
|
P = "<h1>Cam\ping Problem!</h1><h2>%s</h2>"
|
48
50
|
U = Rack::Utils
|
51
|
+
O = {}
|
49
52
|
Apps = []
|
50
53
|
# An object-like Hash.
|
51
54
|
# All Camping query string and cookie variables are loaded as this.
|
@@ -183,7 +186,7 @@ module Camping
|
|
183
186
|
raise "bad route" unless u = c.urls.find{|x|
|
184
187
|
break x if x.scan(p).size == g.size &&
|
185
188
|
/^#{x}\/?$/ =~ (x=g.inject(x){|x,a|
|
186
|
-
x.sub p,U.escape((a
|
189
|
+
x.sub p,U.escape((a.to_param rescue a))}.gsub(/\\(.)/){$1})
|
187
190
|
}
|
188
191
|
h.any?? u+"?"+U.build_query(h[0]) : u
|
189
192
|
end
|
@@ -195,7 +198,7 @@ module Camping
|
|
195
198
|
# self / "styles.css" #=> "styles.css"
|
196
199
|
# self / R(Edit, 1) #=> "/blog/edit/1"
|
197
200
|
#
|
198
|
-
def /(p); p[0]
|
201
|
+
def /(p); p[0] == ?/ ? @root + p : p end
|
199
202
|
|
200
203
|
# Builds a URL route to a controller or a path, returning a URI object.
|
201
204
|
# This way you'll get the hostname and the port number, a complete URL.
|
@@ -235,7 +238,25 @@ module Camping
|
|
235
238
|
module Base
|
236
239
|
attr_accessor :env, :request, :root, :input, :cookies, :state,
|
237
240
|
:status, :headers, :body
|
238
|
-
|
241
|
+
|
242
|
+
T = {}
|
243
|
+
L = :layout
|
244
|
+
|
245
|
+
# Finds a template, returning either:
|
246
|
+
#
|
247
|
+
# false # => Could not find template
|
248
|
+
# true # => Found template in Views
|
249
|
+
# instance of Tilt # => Found template in a file
|
250
|
+
def lookup(n)
|
251
|
+
T.fetch(n.to_sym) do |k|
|
252
|
+
t = Views.method_defined?(k) ||
|
253
|
+
(f = Dir[[O[:views] || "views", "#{n}.*"]*'/'][0]) &&
|
254
|
+
Template.new(f, O[f[/\.(\w+)$/, 1].to_sym] || {})
|
255
|
+
|
256
|
+
O[:dynamic_templates] ? t : T[k] = t
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
239
260
|
# Display a view, calling it by its method name +v+. If a <tt>layout</tt>
|
240
261
|
# method is found in Camping::Views, it will be used to wrap the HTML.
|
241
262
|
#
|
@@ -248,8 +269,15 @@ module Camping
|
|
248
269
|
# end
|
249
270
|
# end
|
250
271
|
#
|
251
|
-
def render(v
|
252
|
-
|
272
|
+
def render(v, *a, &b)
|
273
|
+
if t = lookup(v)
|
274
|
+
o = Hash === a[-1] ? a.pop : {}
|
275
|
+
s = (t == true) ? mab{ send(v, *a, &b) } : t.render(self, o[:locals] || {}, &b)
|
276
|
+
s = render(L, o.merge(L => false)) { s } if v.to_s[0] != ?_ && o[L] != false && lookup(L)
|
277
|
+
s
|
278
|
+
else
|
279
|
+
raise "Can't find template #{v}"
|
280
|
+
end
|
253
281
|
end
|
254
282
|
|
255
283
|
# You can directly return HTML form your controller for quick debugging
|
@@ -262,11 +290,8 @@ module Camping
|
|
262
290
|
# end
|
263
291
|
#
|
264
292
|
# You can also pass true to use the :layout HTML wrapping method
|
265
|
-
def mab(
|
266
|
-
|
267
|
-
s=m.capture(&b)
|
268
|
-
s=m.capture{layout{s}} if l && m.respond_to?(:layout)
|
269
|
-
s
|
293
|
+
def mab(&b)
|
294
|
+
(@mab ||= Mab.new({},self)).capture(&b)
|
270
295
|
end
|
271
296
|
|
272
297
|
# A quick means of setting this controller's status, body and headers
|
@@ -355,7 +380,7 @@ module Camping
|
|
355
380
|
# end
|
356
381
|
# end
|
357
382
|
def to_a
|
358
|
-
@env['rack.session'] = @state
|
383
|
+
@env['rack.session'] = Hash[@state]
|
359
384
|
r = Rack::Response.new(@body, @status, @headers)
|
360
385
|
@cookies.each do |k, v|
|
361
386
|
next if @old_cookies[k] == v
|
@@ -517,11 +542,11 @@ module Camping
|
|
517
542
|
# * Classes with routes are searched in order of their creation.
|
518
543
|
#
|
519
544
|
# So, define your catch-all controllers last.
|
520
|
-
def D(p, m)
|
545
|
+
def D(p, m, e)
|
521
546
|
p = '/' if !p || !p[0]
|
522
547
|
r.map { |k|
|
523
548
|
k.urls.map { |x|
|
524
|
-
return (k.
|
549
|
+
return (k.method_defined?(m)) ?
|
525
550
|
[k, m, *$~[1..-1]] : [I, 'r501', m] if p =~ /^#{x}\/?$/
|
526
551
|
}
|
527
552
|
}
|
@@ -547,9 +572,9 @@ module Camping
|
|
547
572
|
end
|
548
573
|
constants.map { |c|
|
549
574
|
k = const_get(c)
|
550
|
-
k.send :include,C,Base,Helpers,Models
|
575
|
+
k.send :include,C,X,Base,Helpers,Models
|
551
576
|
@r=[k]+r if r-[k]==r
|
552
|
-
k.meta_def(:urls){["/#{c.scan(/.[^A-Z]*/).map(&N.method(:[]))*'/'}"]}if !k.respond_to?:urls
|
577
|
+
k.meta_def(:urls){["/#{c.to_s.scan(/.[^A-Z]*/).map(&N.method(:[]))*'/'}"]}if !k.respond_to?:urls
|
553
578
|
}
|
554
579
|
end
|
555
580
|
end
|
@@ -584,7 +609,7 @@ module Camping
|
|
584
609
|
def call(e)
|
585
610
|
X.M
|
586
611
|
p = e['PATH_INFO'] = U.unescape(e['PATH_INFO'])
|
587
|
-
k,m,*a=X.D p,e['REQUEST_METHOD'].downcase
|
612
|
+
k,m,*a=X.D p,e['REQUEST_METHOD'].downcase,e
|
588
613
|
k.new(e,m).service(*a).to_a
|
589
614
|
rescue
|
590
615
|
r500(:I, k, m, $!, :env => e).to_a
|
@@ -627,6 +652,20 @@ module Camping
|
|
627
652
|
m = a.shift.new(method(:call), *a, &b)
|
628
653
|
meta_def(:call) { |e| m.call(e) }
|
629
654
|
end
|
655
|
+
|
656
|
+
# A hash where you can set different settings.
|
657
|
+
def options
|
658
|
+
O
|
659
|
+
end
|
660
|
+
|
661
|
+
# Shortcut for setting options:
|
662
|
+
#
|
663
|
+
# module Blog
|
664
|
+
# set :secret, "Hello!"
|
665
|
+
# end
|
666
|
+
def set(k, v)
|
667
|
+
O[k] = v
|
668
|
+
end
|
630
669
|
end
|
631
670
|
|
632
671
|
# Views is an empty module for storing methods which create HTML. The HTML
|
@@ -696,6 +735,7 @@ module Camping
|
|
696
735
|
end
|
697
736
|
|
698
737
|
autoload :Mab, 'camping/mab'
|
738
|
+
autoload :Template, 'camping/template'
|
699
739
|
C
|
700
740
|
end
|
701
741
|
|
data/lib/camping.rb
CHANGED
@@ -1,40 +1,45 @@
|
|
1
1
|
require "uri";require "rack";class Object;def meta_def m,&b;(class<<self;self
|
2
2
|
end).send:define_method,m,&b end end;module Camping;C=self;S=IO.read(__FILE__
|
3
|
-
)rescue nil;P="<h1>Cam\ping Problem!</h1><h2>%s</h2>";U=Rack::Utils;Apps=[]
|
3
|
+
)rescue nil;P="<h1>Cam\ping Problem!</h1><h2>%s</h2>";U=Rack::Utils;O={};Apps=[]
|
4
4
|
class H<Hash;def method_missing m,*a;m.to_s=~/=$/?self[$`]=a[0]:a==[]?self[m.
|
5
5
|
to_s]:super end;undef id,type if ??==63;end;module Helpers;def R c,*g;p,h=
|
6
6
|
/\(.+?\)/,g.grep(Hash);g-=h;raise"bad route"unless u=c.urls.find{|x|break x if
|
7
|
-
x.scan(p).size==g.size&&/^#{x}\/?$/=~(x=g.inject(x){|x,a|x.sub p,U.escape((a
|
8
|
-
|
7
|
+
x.scan(p).size==g.size&&/^#{x}\/?$/=~(x=g.inject(x){|x,a|x.sub p,U.escape((a.
|
8
|
+
to_param rescue a))}.gsub(/\\(.)/){$1})};h.any?? u+"?"+U.build_query(h[0]):u end;def
|
9
9
|
/ p;p[0]==?/?@root + p : p end;def URL c='/',*a;c=R(c, *a) if c.respond_to?(
|
10
10
|
:urls);c=self/c;c=@request.url[/.{8,}?(?=\/)/]+c if c[0]==?/;URI c end end
|
11
11
|
module Base;attr_accessor:env,:request,:root,:input,:cookies,:state,:status,
|
12
|
-
:headers,:body;def
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
)
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end;
|
33
|
-
|
34
|
-
k,
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
12
|
+
:headers,:body;T={};L=:layout;def lookup n;T.fetch(n.to_sym){|k|t=Views.
|
13
|
+
method_defined?(k)||(f=Dir[[O[:views]||"views","#{n}.*"]*'/'][0])&&Template.
|
14
|
+
new(f,O[f[/\.(\w+)$/,1].to_sym]||{});O[:dynamic_templates]?t:T[k]=t} end
|
15
|
+
def render(v,*a,&b)if t=lookup(v);o=Hash===a[-1]?a.pop: {};s=(t==true)?mab{
|
16
|
+
send v,*a,&b}: t.render(self,o[:locals]||{},&b);s=render(L,o.merge(L=>false)){s
|
17
|
+
}if v.to_s[0]!=?_&&o[L]!=false&&lookup(L);s;else;raise"Can't find template #{v}"end
|
18
|
+
end;def mab &b;(@mab||=Mab.new({},self)).capture(&b) end;def r s,b,h={};b,h=h,
|
19
|
+
b if Hash===b;@status=s;@headers.merge!(h);@body=b;end;def redirect *a;r 302,'',
|
20
|
+
'Location'=>URL(*a).to_s;end;def r404 p;P%"#{p} not found"end;def r500 k,m,e
|
21
|
+
raise e;end;def r501 m;P%"#{m.upcase} not implemented"end;def to_a;@env[
|
22
|
+
'rack.session']=Hash[@state];r=Rack::Response.new(@body,@status,@headers)
|
23
|
+
@cookies.each{|k,v|next if @old_cookies[k]==v;v={:value=>v,:path=>self/"/"} if
|
24
|
+
String===v;r.set_cookie(k,v)};r.to_a;end;def initialize(env,m) r=@request=Rack::
|
25
|
+
Request.new(@env=env);@root,@input,@cookies,@state,@headers,@status,@method=r.
|
26
|
+
script_name.sub(/\/$/,''),n(r.params),H[@old_cookies = r.cookies],H[r.session],
|
27
|
+
{},m=~/r(\d+)/?$1.to_i: 200,m end;def n h;Hash===h ?h.inject(H[]){|m,(k,v)|m[k]=
|
28
|
+
n(v);m}: h end;def service *a;r=catch(:halt){send(@method,*a)};@body||=r;self
|
29
|
+
end;end;module Controllers;@r=[];class<<self;def r;@r end;def R *u;r=@r;Class.
|
30
|
+
new{meta_def(:urls){u};meta_def(:inherited){|x|r<<x}}end;def D p,m,e;p='/'if !p||
|
31
|
+
!p[0];r.map{|k|k.urls.map{|x|return(k.method_defined? m)?[k,m,*$~[1..-1]]:[I,
|
32
|
+
'r501',m]if p=~/^#{x}\/?$/}};[I,'r404',p] end;N=H.new{|_,x|x.downcase}.merge!(
|
33
|
+
"N"=>'(\d+)',"X"=>'([^/]+)',"Index"=>'');def M;def M;end;constants.map{|c|k=
|
34
|
+
const_get(c);k.send:include,C,X,Base,Helpers,Models;@r=[k]+r if r-[k]==r
|
35
|
+
k.meta_def(:urls){ [ "/#{c.to_s.scan(/.[^A-Z]*/).map(&N.method(:[]))*'/'}"]}if !k.
|
36
|
+
respond_to?:urls}end end;I=R();end;X=Controllers;class<<self;def goes m;Apps<<
|
37
|
+
eval(S.gsub(/Camping/,m.to_s),TOPLEVEL_BINDING) end;def call e;X.M
|
38
|
+
p=e['PATH_INFO']=U.unescape(e['PATH_INFO']);k,m,*a=X.D p,e['REQUEST_METHOD'].
|
39
|
+
downcase,e;k.new(e,m).service(*a).to_a;rescue;r500(:I,k,m,$!,:env=>e).to_a;end
|
40
|
+
def method_missing m,c,*a;X.M;h=Hash===a[-1]?a.pop: {};e=H[Rack::MockRequest.
|
41
|
+
env_for('',h.delete(:env)||{})];k=X.const_get(c).new(e,m.to_s);h.each{|i,v|k.
|
42
|
+
send"#{i}=",v};k.service(*a);end;def use*a,&b;m=a.shift.new(method(:call),*a,&b)
|
43
|
+
meta_def(:call){|e|m.call(e)}end;def options;O end;def set k,v;O[k]=v end end
|
44
|
+
module Views;include X,Helpers end;module Models;autoload:Base,'camping/ar';end
|
45
|
+
autoload:Mab,'camping/mab';autoload:Template,'camping/template';C end
|