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.
@@ -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