camping 1.3 → 1.4
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 +12 -0
- data/bin/camping +14 -14
- data/examples/blog/blog.db +0 -0
- data/examples/blog/blog.rb +28 -15
- data/examples/blog/camping.log +82 -0
- data/examples/blog/foo.log +0 -0
- data/examples/blog/test.yml +0 -0
- data/examples/camping.log +1111 -0
- data/examples/charts/1.gif +0 -0
- data/examples/charts/2.gif +0 -0
- data/examples/charts/3.gif +0 -0
- data/examples/serve +30 -33
- data/examples/serve.db +0 -0
- data/examples/tepee/tepee.rb +11 -4
- data/extras/flipbook_rdoc.rb +32 -21
- data/extras/permalink.gif +0 -0
- data/lib/camping-unabridged.rb +209 -155
- data/lib/camping.rb +48 -51
- data/lib/camping/session.rb +123 -0
- data/lib/camping/webrick.rb +20 -0
- metadata +21 -8
data/lib/camping.rb
CHANGED
|
@@ -1,53 +1,50 @@
|
|
|
1
|
-
%w[rubygems active_record markaby metaid tempfile].each{|l|require l}
|
|
1
|
+
%w[rubygems active_record markaby metaid tempfile uri].each{|l|require l}
|
|
2
2
|
module Camping;C=self;F=__FILE__;S=IO.read(F).gsub(/_+FILE_+/,F.dump)
|
|
3
|
-
module Helpers;def R c,*args;p=/\(.+?\)/;args.inject(c.urls.find{|x|x.scan(p
|
|
4
|
-
|
|
5
|
-
a).to_s)}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
end;def
|
|
13
|
-
|
|
14
|
-
'
|
|
15
|
-
|
|
16
|
-
b
|
|
17
|
-
|
|
18
|
-
/m};fn=fh[:name];if fh[:filename];fh[:type]
|
|
19
|
-
\r\n|\Z)/m;fh[:tempfile]=Tempfile.new(
|
|
20
|
-
rewind;self}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
NotFound;def get
|
|
29
|
-
end;class ServerError;include Base;def get
|
|
30
|
-
h2 "#{k}.#{m}";h3 "#{e.class} #{e.message}:";ul{
|
|
31
|
-
)end end;class<<self;def R
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
class Mab<Markaby::Builder;include Views
|
|
50
|
-
def tag!(*g,&b);h=g[-1];[:href,:action].each{|a|(h[a]=self/h[a])rescue 0}
|
|
51
|
-
super;end;end;class H<HashWithIndifferentAccess;def method_missing(m,*a)
|
|
3
|
+
module Helpers;def R c,*args;p=/\(.+?\)/;args.inject(c.urls.find{|x|x.scan(p).
|
|
4
|
+
size==args.size}.dup){|str,a|str.sub(p,(a.__send__(a.class.primary_key)rescue
|
|
5
|
+
a).to_s)} end;def URL c='/',*a;c=R(c,*a)if c.respond_to?:urls;c=self/c;c=
|
|
6
|
+
"http://"+@env.HTTP_HOST+c if c[/^\//];URI(c) end;def / p;p[/^\//]?@root+p:p end
|
|
7
|
+
def errors_for o;ul.errors{o.errors.each_full{|x|li x}}if o.errors.any? end end
|
|
8
|
+
module Base;include Helpers;attr_accessor :input,:cookies,:env,:headers,:body,
|
|
9
|
+
:status,:root;def method_missing m,*a,&b;s=m==:render ? markaview(*a,&b):eval(
|
|
10
|
+
"markaby.#{m}(*a,&b)");s=markaview(:layout){s} if Views.method_defined?:layout
|
|
11
|
+
r 200,s.to_s end;def r s,b,h={};@status=s;@headers.merge!(h);@body=b end;def
|
|
12
|
+
redirect *a;r 302,'','Location'=>URL(*a) end;def initialize r,e,m;e=H[e.to_hash]
|
|
13
|
+
@status,@method,@env,@headers,@root=200,m.downcase,e,{'Content-Type'=>"text/htm\
|
|
14
|
+
l"},e.SCRIPT_NAME.sub(/\/$/,'');@k=C.kp e.HTTP_COOKIE;q=C.qs_parse e.QUERY_STRING
|
|
15
|
+
@in=r;if %r|\Amultipart/form-.*boundary=\"?([^\";,]+)|n.match e.CONTENT_TYPE;b=
|
|
16
|
+
"--#$1";@in.read.split(/(?:\r?\n|\A)#{Regexp.quote b}(?:--)?\r\n/m).map{|y|h,v=y.
|
|
17
|
+
split "\r\n\r\n",2;fh={};[:name,:filename].map{|x|fh[x]=$1 if h=~/^Content-Di.+\
|
|
18
|
+
: form-data;.*(?:\s#{x}="([^"]+)")/m};fn=fh[:name];if fh[:filename];fh[:type]=
|
|
19
|
+
$1 if h=~/^Content-Type: (.+?)(\r\n|\Z)/m;fh[:tempfile]=Tempfile.new(:C).
|
|
20
|
+
instance_eval{binmode;write v;rewind;self}else;fh=v end;q[fn]=fh if fn}elsif
|
|
21
|
+
@method=="post";q.merge! C.qs_parse(@in.read) end;@cookies,@input=
|
|
22
|
+
@k.dup,q.dup end;def service *a;@body=send(@method,*a)if respond_to?@method
|
|
23
|
+
@headers["Set-Cookie"]=@cookies.map{|k,v|"#{k}=#{C.escape(v)}; path=#{self/"/"}\
|
|
24
|
+
" if v != @k[k]}.compact;self end;def to_s;"Status: #{@status}\n#{@headers.map{
|
|
25
|
+
|k,v|[*v].map{|x|"#{k}: #{x}"}*"\n"}*"\n"}\n\n#{@body}" end;def markaby;Mab.new(
|
|
26
|
+
instance_variables.map{|iv|[iv[1..-1],instance_variable_get(iv)]}) end;def
|
|
27
|
+
markaview m,*a,&b;h=markaby;h.send m,*a,&b;h.to_s end end;class R;include Base
|
|
28
|
+
end;module Controllers;class NotFound;def get p;r(404,div{h1 "Cam\ping Problem!"
|
|
29
|
+
h2 p+" not found"}) end end;class ServerError;include Base;def get k,m,e;r(500,
|
|
30
|
+
Mab.new{h1 "Cam\ping Problem!";h2 "#{k}.#{m}";h3 "#{e.class} #{e.message}:";ul{
|
|
31
|
+
e.backtrace.each{|bt|li(bt)}}}.to_s)end end;class<<self;def R *urls;Class.new(
|
|
32
|
+
R){meta_def(:urls){urls}}end;def D path;constants.inject(nil){|d,c|k=const_get c
|
|
33
|
+
k.meta_def(:urls){["/#{c.downcase}"]}if !(k<R);d||([k,$~[1..-1]]if k.urls.find{
|
|
34
|
+
|x|path=~/^#{x}\/?$/})}||[NotFound,[path]] end end end;class<<self;def goes m
|
|
35
|
+
eval(S.gsub(/Camping/,m.to_s),TOPLEVEL_BINDING)end;def escape s;s.to_s.gsub(
|
|
36
|
+
/([^ a-zA-Z0-9_.-]+)/n){'%'+$1.unpack('H2'*$1.size).join('%').upcase}.tr ' ','+'
|
|
37
|
+
end;def un s;s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){[$1.delete('%'
|
|
38
|
+
)].pack('H*')} end;def qs_parse q,d='&;';m=proc{|_,o,n|o.merge(n,&m)rescue([*o
|
|
39
|
+
]<<n)};q.to_s.split(/[#{d}] */n).inject(H[]){|h,p|k,v=un(p).split('=',2)
|
|
40
|
+
h.merge k.split(/[\]\[]+/).reverse.inject(v){|x,i|H[i,x]},&m}end;def kp(s);c=
|
|
41
|
+
qs_parse(s,';,')end;def run r=$stdin,e=ENV;k,a=Controllers.D un("/#{e['PATH_INFO']
|
|
42
|
+
}".gsub(/\/+/,'/'));k.send:include,C,Base,Models;k.new(r,e,(m=e['REQUEST_METHOD'
|
|
43
|
+
]||"GET")).service *a;rescue=>x;Controllers::ServerError.new(r,e,'get').service(
|
|
44
|
+
k,m,x)end end;module Views;include Controllers,Helpers end;module Models;A=
|
|
45
|
+
ActiveRecord;Base=A::Base;def Base.table_name_prefix;"#{name[/^(\w+)/,1]}_".
|
|
46
|
+
downcase.sub(/^(#{A}|camping)_/i,'')end end;class Mab<Markaby::Builder;include \
|
|
47
|
+
Views;def tag! *g,&b;h=g[-1];[:href,:action,:src].map{|a|(h[a]=self/h[a])rescue
|
|
48
|
+
0};super end end;H=HashWithIndifferentAccess;class H;def method_missing m,*a
|
|
52
49
|
if m.to_s=~/=$/;self[$`]=a[0];elsif a.empty?;self[m];else;raise NoMethodError,
|
|
53
|
-
"#{m}"
|
|
50
|
+
"#{m}" end end end end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# == About camping/session.rb
|
|
2
|
+
#
|
|
3
|
+
# This file contains two modules which supply basic sessioning to your Camping app.
|
|
4
|
+
# Again, we're dealing with a pretty little bit of code: approx. 60 lines.
|
|
5
|
+
#
|
|
6
|
+
# * Camping::Models::Session is a module which adds a single <tt>sessions</tt> table
|
|
7
|
+
# to your database.
|
|
8
|
+
# * Camping::Session is a module which you will mix into your application (or into
|
|
9
|
+
# specific controllers which require sessions) to supply a <tt>@state</tt> variable
|
|
10
|
+
# you can use in controllers and views.
|
|
11
|
+
#
|
|
12
|
+
# For a basic tutorial, see the *Getting Started* section of the Camping::Session module.
|
|
13
|
+
require 'camping'
|
|
14
|
+
|
|
15
|
+
module Camping::Models
|
|
16
|
+
# A database table for storing Camping sessions. Contains a unique 32-character hashid, a
|
|
17
|
+
# creation timestamp, and a column of serialized data called <tt>ivars</tt>.
|
|
18
|
+
class Session < Base
|
|
19
|
+
serialize :ivars
|
|
20
|
+
def []=(k, v) # :nodoc:
|
|
21
|
+
self.ivars[k] = v
|
|
22
|
+
end
|
|
23
|
+
def [](k) # :nodoc:
|
|
24
|
+
self.ivars[k] rescue nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
RAND_CHARS = [*'A'..'Z'] + [*'0'..'9'] + [*'a'..'z']
|
|
28
|
+
|
|
29
|
+
# Generates a new session ID and creates a row for the new session in the database.
|
|
30
|
+
def self.generate cookies
|
|
31
|
+
rand_max = RAND_CHARS.size
|
|
32
|
+
sid = (0...32).inject("") { |ret,_| ret << RAND_CHARS[rand(rand_max)] }
|
|
33
|
+
sess = Session.create :hashid => sid, :ivars => Camping::H[]
|
|
34
|
+
cookies.camping_sid = sess.hashid
|
|
35
|
+
sess
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Gets the existing session based on the <tt>camping_sid</tt> available in cookies.
|
|
39
|
+
# If none is found, generates a new session.
|
|
40
|
+
def self.persist cookies
|
|
41
|
+
if cookies.camping_sid
|
|
42
|
+
session = Camping::Models::Session.find_by_hashid cookies.camping_sid
|
|
43
|
+
end
|
|
44
|
+
unless session
|
|
45
|
+
session = Camping::Models::Session.generate cookies
|
|
46
|
+
end
|
|
47
|
+
session
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Builds the session table in the database. To be used in your application's
|
|
51
|
+
# <tt>create</tt> method.
|
|
52
|
+
#
|
|
53
|
+
# Like so:
|
|
54
|
+
#
|
|
55
|
+
# def Blog.create
|
|
56
|
+
# Camping::Models::Session.create_schema
|
|
57
|
+
# unless Blog::Models::Post.table_exists?
|
|
58
|
+
# ActiveRecord::Schema.define(&Blog::Models.schema)
|
|
59
|
+
# end
|
|
60
|
+
# end
|
|
61
|
+
#
|
|
62
|
+
def self.create_schema
|
|
63
|
+
unless table_exists?
|
|
64
|
+
ActiveRecord::Schema.define do
|
|
65
|
+
create_table :sessions, :force => true do |t|
|
|
66
|
+
t.column :id, :integer, :null => false
|
|
67
|
+
t.column :hashid, :string, :limit => 32
|
|
68
|
+
t.column :created_at, :datetime
|
|
69
|
+
t.column :ivars, :text
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
reset_column_information
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
module Camping
|
|
79
|
+
# The Camping::Session module is designed to be mixed into your application or into specific
|
|
80
|
+
# controllers which require sessions. This module defines a <tt>service</tt> method which
|
|
81
|
+
# intercepts all requests handed to those controllers.
|
|
82
|
+
#
|
|
83
|
+
# == Getting Started
|
|
84
|
+
#
|
|
85
|
+
# To get sessions working for your application:
|
|
86
|
+
#
|
|
87
|
+
# 1. <tt>require 'camping/session'</tt>
|
|
88
|
+
# 2. Mixin the module: <tt>module YourApp; include Camping::Session end</tt>
|
|
89
|
+
# 3. In your application's <tt>create</tt> method, add a call to <tt>Camping::Models::Schema.create_schema</tt>
|
|
90
|
+
# 4. Throughout your application, use the <tt>@state</tt> var like a hash to store your application's data.
|
|
91
|
+
#
|
|
92
|
+
# If you are unfamiliar with the <tt>create</tt> method, see
|
|
93
|
+
# http://code.whytheluckystiff.net/camping/wiki/GiveUsTheCreateMethod.
|
|
94
|
+
#
|
|
95
|
+
# == A Few Notes
|
|
96
|
+
#
|
|
97
|
+
# * The session ID is stored in a cookie. Look in <tt>@cookies.camping_sid</tt>.
|
|
98
|
+
# * The session data is stored in the <tt>sessions</tt> table in your database.
|
|
99
|
+
# * All mounted Camping apps using this class will use the same database table.
|
|
100
|
+
# * However, your application's data is stored in its own hash.
|
|
101
|
+
# * Session data is only saved if it has changed.
|
|
102
|
+
module Session
|
|
103
|
+
# This <tt>service</tt> method, when mixed into controllers, intercepts requests
|
|
104
|
+
# and wraps them with code to start and close the session. If a session isn't found
|
|
105
|
+
# in the database it is created. The <tt>@state</tt> variable is set and if it changes,
|
|
106
|
+
# it is saved back into the database.
|
|
107
|
+
def service(*a)
|
|
108
|
+
session = Camping::Models::Session.persist @cookies
|
|
109
|
+
app = self.class.name.gsub(/^(\w+)::.+$/, '\1')
|
|
110
|
+
@state = (session[app] ||= Camping::H[])
|
|
111
|
+
hash_before = Marshal.dump(@state).hash
|
|
112
|
+
s = super(*a)
|
|
113
|
+
if session
|
|
114
|
+
hash_after = Marshal.dump(@state).hash
|
|
115
|
+
unless hash_before == hash_after
|
|
116
|
+
session[app] = @state
|
|
117
|
+
session.save
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
s
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'camping'
|
|
2
|
+
require 'webrick/httpservlet/abstract.rb'
|
|
3
|
+
|
|
4
|
+
class WEBrick::CampingHandler < WEBrick::HTTPServlet::AbstractServlet
|
|
5
|
+
def initialize(server, klass)
|
|
6
|
+
super(server, klass)
|
|
7
|
+
@klass = klass
|
|
8
|
+
end
|
|
9
|
+
def do_GET(req, resp)
|
|
10
|
+
controller = @klass.run((req.body and StringIO.new(req.body)), req.meta_vars)
|
|
11
|
+
resp.status = controller.status
|
|
12
|
+
controller.headers.each do |k, v|
|
|
13
|
+
[*v].each do |vi|
|
|
14
|
+
resp[k] = vi
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
resp.body = controller.body
|
|
18
|
+
end
|
|
19
|
+
alias_method :do_POST, :do_GET
|
|
20
|
+
end
|
metadata
CHANGED
|
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
|
3
3
|
specification_version: 1
|
|
4
4
|
name: camping
|
|
5
5
|
version: !ruby/object:Gem::Version
|
|
6
|
-
version: "1.
|
|
7
|
-
date: 2006-
|
|
6
|
+
version: "1.4"
|
|
7
|
+
date: 2006-04-11 00:00:00 -06:00
|
|
8
8
|
summary: miniature rails for stay-at-home moms
|
|
9
9
|
require_paths:
|
|
10
10
|
- lib
|
|
@@ -34,22 +34,35 @@ files:
|
|
|
34
34
|
- examples/blog
|
|
35
35
|
- examples/charts
|
|
36
36
|
- examples/campsh
|
|
37
|
+
- examples/camping.log
|
|
37
38
|
- examples/serve
|
|
39
|
+
- examples/serve.db
|
|
38
40
|
- examples/tepee/tepee.rb
|
|
39
41
|
- examples/tepee/start
|
|
40
|
-
- examples/blog/
|
|
42
|
+
- examples/blog/camping.log
|
|
41
43
|
- examples/blog/blog.rb
|
|
42
44
|
- examples/blog/start
|
|
45
|
+
- examples/blog/blog.sqlite3
|
|
46
|
+
- examples/blog/test.yml
|
|
47
|
+
- examples/blog/blog.db
|
|
48
|
+
- examples/blog/foo.log
|
|
43
49
|
- examples/charts/charts
|
|
44
|
-
- examples/charts/pie.rb
|
|
45
50
|
- examples/charts/charts.rb
|
|
51
|
+
- examples/charts/pie.rb
|
|
52
|
+
- examples/charts/1.gif
|
|
46
53
|
- examples/charts/start
|
|
54
|
+
- examples/charts/2.gif
|
|
55
|
+
- examples/charts/3.gif
|
|
47
56
|
- examples/campsh/campsh.rb
|
|
57
|
+
- lib/camping
|
|
48
58
|
- lib/camping.rb
|
|
49
59
|
- lib/camping-unabridged.rb
|
|
60
|
+
- lib/camping/session.rb
|
|
61
|
+
- lib/camping/webrick.rb
|
|
50
62
|
- bin/camping
|
|
51
|
-
- extras/
|
|
63
|
+
- extras/permalink.gif
|
|
52
64
|
- extras/Camping.gif
|
|
65
|
+
- extras/flipbook_rdoc.rb
|
|
53
66
|
test_files: []
|
|
54
67
|
|
|
55
68
|
rdoc_options:
|
|
@@ -85,16 +98,16 @@ dependencies:
|
|
|
85
98
|
requirements:
|
|
86
99
|
- - ">="
|
|
87
100
|
- !ruby/object:Gem::Version
|
|
88
|
-
version:
|
|
101
|
+
version: 1.14.0
|
|
89
102
|
version:
|
|
90
103
|
- !ruby/object:Gem::Dependency
|
|
91
104
|
name: markaby
|
|
92
105
|
version_requirement:
|
|
93
106
|
version_requirements: !ruby/object:Gem::Version::Requirement
|
|
94
107
|
requirements:
|
|
95
|
-
- - "
|
|
108
|
+
- - ">="
|
|
96
109
|
- !ruby/object:Gem::Version
|
|
97
|
-
version: "0.
|
|
110
|
+
version: "0.4"
|
|
98
111
|
version:
|
|
99
112
|
- !ruby/object:Gem::Dependency
|
|
100
113
|
name: metaid
|