camping 1.3 → 1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|