camping 1.3 → 1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- ).size==args.size}.dup){|str,a|str.sub(p,(a.__send__(a.class.primary_key)rescue
5
- a).to_s)};end;def / p;p[/^\//]?@root+p:p end;def errors_for(o);ul.errors{o.
6
- errors.each_full{|er|li er}}unless o.errors.empty?;end;end;module Controllers
7
- module Base; include Helpers;attr_accessor :input,:cookies,:env,:headers,:body,
8
- :status,:root;def method_missing(m,*a,&b);str=m==:render ? markaview(*a,
9
- &b):eval("markaby.#{m}(*a,&b)");str=markaview(:layout){str} if Views.method_defined? :layout;r(
10
- 200,str.to_s);end;def r(s,b,h={});@status=s;@headers.merge!(h);@body=b;end;def
11
- redirect(c,*args);c=R(c,*args)if c.respond_to?:urls;r(302,'','Location'=>self/c)
12
- end;def service(r,e,m,a)@status,@env,@headers,@root=200,e,{'Content-Type'=>'text/html'},e['SCRIPT_NAME'];cook=C.kp(
13
- e['HTTP_COOKIE']);qs=C.qs_parse(e['QUERY_STRING']);if "post"==m;inp=r.read(e[
14
- 'CONTENT_LENGTH'].to_i);if %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)|n.
15
- match(e['CONTENT_TYPE']);b="--#$1";inp.split(/(?:\r?\n|\A)#{Regexp::quote(
16
- b)}(?:--)?\r\n/m).each{|pt|h,v=pt.split("\r\n\r\n",2);fh={};[:name,:filename].
17
- each{|x|fh[x]=$1 if h=~/^Content-Disposition: form-data;.*(?:\s#{x}="([^"]+)")\
18
- /m};fn=fh[:name];if fh[:filename];fh[:type]=$1 if h =~ /^Content-Type: (.+?)(\
19
- \r\n|\Z)/m;fh[:tempfile]=Tempfile.new("C").instance_eval{binmode;write v
20
- rewind;self};else;fh=v;end;qs[fn]=fh if fn};else;qs.merge!(C.qs_parse(inp));end
21
- end;@cookies, @input = cook.dup, qs.dup;@body=send(m,*a) if respond_to? m;@headers["Set-Cookie"]=@cookies.map{|k,v|"#{k}=#{C.
22
- escape(v)}; path=#{self/"/"}" if v != cook[k]}.compact;self;end;def to_s;"Status: #{
23
- @status}\n#{@headers.map{|k,v|[*v].map{
24
- |x|"#{k}: #{x}"}*"\n"}*"\n"}\n\n#{@body}";end;def markaby;Mab.new(
25
- instance_variables.map{|iv|[iv[1..-1],instance_variable_get(iv)]});end;def
26
- markaview(m,*a,&b);h=markaby;h.send(m,*a,&b);h.to_s
27
- end;end;class R;include Base end;class
28
- NotFound;def get(p);r(404,div{h1("Cam\ping Problem!")+h2("#{p} not found")});end
29
- end;class ServerError;include Base;def get(k,m,e);r(500,Mab.new{h1 "Cam\ping Problem!"
30
- h2 "#{k}.#{m}";h3 "#{e.class} #{e.message}:";ul{e.backtrace.each{|bt|li(bt)}}}.to_s
31
- )end end;class<<self;def R(*urls);Class.new(R){meta_def(:urls){urls}};end;def
32
- D(path);constants.inject(nil){|d,c|k=
33
- const_get(c);k.meta_def(:urls){["/#{c.downcase}"]}if !(k<R);d||([k, $~[1..-1]
34
- ] if k.urls.find { |x| path =~ /^#{x}\/?$/ })}||[NotFound, [path]];end end end
35
- class<<self;def goes m;eval(S.gsub(/Camping/,m.to_s),TOPLEVEL_BINDING)end;def
36
- escape s;s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n){'%'+$1.unpack('H2'*$1.size).join(
37
- '%').upcase}.tr(' ','+') end;def unescape(s);s.tr('+', ' ').gsub(/((?:%[0-9a-f\
38
- A-F]{2})+)/n){[$1.delete('%')].pack('H*')} end;def qs_parse qs,d='&;';m=proc{
39
- |_,o,n|o.merge(n,&m)rescue([*o]<<n)};qs.to_s.split(/[#{d}] */n).inject(H[]){
40
- |h,p|k,v=unescape(p).split('=',2);h.merge(k.split(/[\]\[]+/).reverse.inject(v){
41
- |x,i|H[i,x]},&m)}end;def kp(s);c=qs_parse(s,';,');end
42
- def run(r=$stdin,e=ENV);begin;k,a=Controllers.D "/#{e['PATH_INFO']}".
43
- gsub(%r!/+!,'/');m=e['REQUEST_METHOD']||"GET";k.send :include,C,Controllers::Base,
44
- Models;o=k.new;o.service(r,e,m.downcase,a);rescue\
45
- =>x;Controllers::ServerError.new.service(r,e,"get",[k,m,x]);end;end;end
46
- module Views; include Controllers,Helpers end;module Models
47
- A=ActiveRecord;Base=A::Base;def Base.table_name_prefix;"#{name[/^(\w+)/,1]}_".
48
- downcase.sub(/^(#{A}|camping)_/i,'');end;end
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}";end;end;end;end
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.3"
7
- date: 2006-02-08 00:00:00 -07:00
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/blog.sqlite3
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/flipbook_rdoc.rb
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: "1.13"
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.2"
110
+ version: "0.4"
98
111
  version:
99
112
  - !ruby/object:Gem::Dependency
100
113
  name: metaid