# Camping 2.0 - minature rails for stay-at-home moms

**URL:** <https://www.ruby-forum.com/t/camping-2-0-minature-rails-for-stay-at-home-moms/226063>\
**Category:** Ruby\
**Created:** [April 9, 2010, 4:48pm UTC](https://www.ruby-forum.com/t/camping-2-0-minature-rails-for-stay-at-home-moms/226063 "2010-04-09T16:48:15Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![judofyr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/90ced4/32.png) [@judofyr](https://www.ruby-forum.com/u/judofyr)\
**Post date:** [April 9, 2010, 4:48pm UTC](https://www.ruby-forum.com/t/camping-2-0-minature-rails-for-stay-at-home-moms/226063/1 "2010-04-09T16:48:15Z")

</div>

require “uri”;require “rack”;class Object;def meta\_def  
m,&b;(class\<\<self;self  
end).send:define\_method,m,&b end end;module  
Camping;C=self;S=IO.read( **FILE**  
)rescue nil;P=“

# Cam\ping Problem!

## %s
”;U=Rack::Utils;Apps=[]  
class H\<Hash;def method\_missing  
m,\*a;m.to\_s=~/=$/?self[$`]=a[0]:a==[]?self[m.  
to\_s]:super end;undef id,type if ??==63;end;module Helpers;def R  
c,\*g;p,h=  
/(.+?)/,g.grep(Hash);g-=h;raise"bad route"unless  
u=c.urls.find{|x|break x if  
x.scan(p).size==g.size&&/^#{x}/?$/=~(x=g.inject(x){|x,a|x.sub  
p,U.escape((a[  
a.class.primary\_key]rescue a))})};h.any?? u+“?”+U.build\_query(h[0]):u  
end;def  
/ p;p[0]==?/?@root + p : p end;def URL c=‘/’,\*a;c=R(c, _a) if  
c.respond\_to?(  
:urls);c=self/c;c=@request.url[/.{8,}?(?=/)/]+c if c[0]==?/;URI c end  
end  
module  
Base;attr\_accessor:env,:request,:root,:input,:cookies,:state,:status,  
:headers,:body;def render v,a,&b;mab(/^/!~v.to\_s){send(v,\*a,&b)}  
end;def  
mab l=nil,&b;m=Mab.new({},self);s=m.capture(&b);s=m.capture{layout{s}}  
if l &&  
m.respond\_to?(:layout);s end;def r s,b,h={};b,h=h,b if  
Hash===b;@status=s;  
 @headers.merge!(h);@body=b;end;def redirect \*a;r  
302,‘’,‘Location’=\>URL(\*a).  
to\_s;end;def r404 p;P%“#{p} not found"end;def r500 k,m,e;raise e;end;def  
r501 m  
P%”#{m.upcase} not implemented"end;def  
to\_a;@env[‘rack.session’]=@state;r=Rack::  
Response.new(@body,@status,@headers);@cookies.each{|k,v|next if  
 @old\_cookies[  
k]==v;v={:value=\>v,:path=\>self/“/”} if  
String===v;r.set\_cookie(k,v)};r.to\_a;end  
def initialize(env,m)  
r=@request=Rack::Request.new(@env=env);@root,@input,  
 @cookies,@state,@headers,@status,@method=r.script\_name.sub(//$/,‘’),n(r.params  
),H[@old\_cookies = r.cookies],H[r.session],{},m=~/r(\d+)/?$1.to\_i: 200,m  
end;def  
n h;Hash===h ?h.inject(H[]){|m,(k,v)|m[k]=n(v);m}: h end;def service  
\*a;r=catch(  
:halt){send(@method,\*a)};@body||=r;self;end;end;module  
Controllers;@r=[];class\<\<  
self;def r;@r end;def R  
 u;r=@r;Class.new{meta\_def(:urls){u};meta\_def(:inherited  
){|x|r\<\<x}}end;def D p,m;p='/'if  
!p||!p[0];r.map{|k|k.urls.map{|x|return(k.  
instance\_method(m)rescue nil)?[k,m,$~[1…-1]]:[I,‘r501’,m]if  
p=~/^#{x}/?$/}}  
[I,‘r404’,p] end;N=H.new{|,x|x.downcase}.merge!  
“N”=\>‘(\d+)’,“X”=\>‘([^/]+)’,  
“Index”=\>‘’;def M;def  
M;end;constants.map{|c|k=const\_get(c);k.send:include,C,  
Base,Helpers,Models;@r=[k]+r if r-[k]==r;k.meta\_def(:urls){ [  
"/#{c.scan(  
/.[^A-Z]/).map(&N.method(:[]))_‘/’}“]}if !k.respond\_to?:urls}end  
end;I=R()  
end;X=Controllers;class\<\<self;def goes  
m;Apps\<\<eval(S.gsub(/Camping/,m.to\_s),  
TOPLEVEL\_BINDING) end;def call  
e;X.M;p=e[‘PATH\_INFO’]=U.unescape(e[‘PATH\_INFO’])  
k,m,\*a=X.D  
p,e[‘REQUEST\_METHOD’].downcase;k.new(e,m).service(\*a).to\_a;rescue  
r500(:I,k,m,$!,:env=\>e).to\_a;end;def method\_missing  
m,c,\*a;X.M;h=Hash===a[-1]?  
a.pop:  
{};e=H[Rack::MockRequest.env\_for(‘’,h.delete(:env)||{})];k=X.const\_get(c  
).new(e,m.to\_s);h.each{|i,v|k.send”#{i}=",v};k.service(_a);end;def  
use_a,&b;m=a.  
shift.new(method(:call),\*a,&b);meta\_def(:call){|e|m.call(e)}end  
end;module Views  
include X,Helpers end;module Models;autoload:Base,  
‘camping/ar’;end;autoload:Mab,‘camping/mab’;C end

* * *

Wow. After 199 commits, 11875 lines of diff and 1284 days, it’s an honor  
to  
present a new, freshly baked version of the microframework; now built  
upon  
Rack and weighing only 3072 tiny bytes. (That’s exactly 3k!)

```
gem install camping

```

Home: [http://whywentcamping.com/](http://whywentcamping.com/) (currently only redirects to the docs)  
Docs: [http://camping.rubyforge.org/](http://camping.rubyforge.org/)  
Code/wiki/bugs: [GitHub - camping/camping: the 5k pocket full-of-gags web microframework](http://github.com/camping/camping)  
Mailing list: [http://rubyforge.org/mailman/listinfo/camping-list](http://rubyforge.org/mailman/listinfo/camping-list)

~\> Wait a second, you’re not \_why!

Well, no. He went camping, so we decided to commandeer and steer this  
ship  
back on course. I’m merely a scoutmaster; it’s the community who’s in  
charge.  
Want to have an impact on Camping? Just join the mailing list, and your  
voice  
will be heard.

~\> What’s new?

Let’s start with Rack.

Every Camping app is now a Rack app. This is your [config.ru](http://config.ru):

```
require 'blog'
run Blog

```

If your app requires a middleware, you can inject it inside your app:

```
module Blog
  use Rack::MethodOverride
end

```

Sessions are now simply a wrapper around env[‘rack.session’], so it’s  
easy as  
pie to `use Other::SessionBackends`.

Ironicly, the methods Rack stole from Camping are no longer in Camping,  
since  
it’s shorter to simply call those in Rack 🙂

Next up: The book - [http://camping.rubyforge.org/book.html](http://camping.rubyforge.org/book.html)

Not really a book, but it should get you started with Camping pretty  
quick. It’s  
far from complete, but in the end you should know plenty about both  
Camping,  
Rack, HTTP and other frameworks. Web development is a huge field in Ruby  
and can  
be a little confusing for newcomers. This book should give you a gentle  
introduction together with pointers to where you could go for more.

This book isn’t written yet. Let me repeat that: This book isn’t  
written yet. Nothing is set in stone. These are basically just some of  
mine  
ideas - what I wish was there some years ago. But I’m neither the author  
nor  
the reader, so I want YOU to tell me how it really should be. It’s  
open-source  
after all.

Being open-source means you are free to do whatever you want. Does that  
sentence suck? That paragraph is badly phrased? That chapter doesn’t  
belong  
there? Rewrite it! Reorganize the whole book! Just make sure to tell the  
rest  
why it’s better.

Being open-source ALSO means you sometimes have to give up your perfect  
chapter. Realize it wasn’t as good as you thought. It’s tough, but  
that’s how  
it’s going to be.

Okay, now: Simpler routes

The most used line is Camping apps has to be:

```
class Index < R '/'

```

So \_why commited and now you can write:

```
class Index # matches /
class Posts # matches /posts
class PostX # matches /post/([^/]+)
class UserN # matches /user/(\d+)

```

~\> Interesting. Is 1.5 still supported? What should I do to upgrade my  
app?

No more development will be done for 1.5, so we recommend that you  
upgrade  
your app to 2.0. Rack::Adapter::Camping will be removed in the next  
release of  
Rack, so if you’re using it you should absolutely switch to Camping 2.0.

Plese read  
[http://camping.rubyforge.org/book/51\_upgrading.html#from-15-to-20](http://camping.rubyforge.org/book/51_upgrading.html#from-15-to-20)  
for upgrade notes and if you still have any problems, please let us know  
and  
we’ll update it.

~\> What will we see 2.1?

That’s up to you! What would you like to see? You don’t necessarily have  
to  
implement it yourself, just tell the rest on the mailing list and maybe  
someone else helps out.

Sean Busbey is trying to make migrations suck less, and I want to make  
it even  
more Rackified. And we’ll all be smashing bugs.

~\> Help, I’m stuck! Where should I go?

The mailing list: [http://rubyforge.org/mailman/listinfo/camping-list](http://rubyforge.org/mailman/listinfo/camping-list)

You can also try #camping on [irc.freenode.net](http://irc.freenode.net):  
[http://java.freenode.net/?channel=camping](http://java.freenode.net/?channel=camping)

// Magnus H.

---

<div class="post-metadata">

**Author:** ![judofyr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/90ced4/32.png) [@judofyr](https://www.ruby-forum.com/u/judofyr)\
**Post date:** [April 9, 2010, 5:22pm UTC](https://www.ruby-forum.com/t/camping-2-0-minature-rails-for-stay-at-home-moms/226063/2 "2010-04-09T17:22:10Z")

</div>

Magnus H. wrote:

> Wow. After 199 commits, 11875 lines of diff and 1284 days, it’s an honor  
> to  
> present a new, freshly baked version of the microframework; now built  
> upon  
> Rack and weighing only 3072 tiny bytes. (That’s exactly 3k!)
> 
> ```
> gem install camping
> 
> ```

Sweet!  
His spirit goes on. Grats to the team!

---

<div class="post-metadata">

**Author:** ![judofyr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/90ced4/32.png) [@judofyr](https://www.ruby-forum.com/u/judofyr)\
**Post date:** [April 9, 2010, 6:51pm UTC](https://www.ruby-forum.com/t/camping-2-0-minature-rails-for-stay-at-home-moms/226063/3 "2010-04-09T18:51:49Z")

</div>

Magnus H. wrote:

> require “uri”;require “rack”;class Object;def meta\_def m,&b;(class\<\<self;self

With this post, you have single-handedly restored the ruby-talk  
signal-to-noise ratio to 2002 levels.

---

<div class="post-metadata">

**Author:** ![judofyr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/90ced4/32.png) [@judofyr](https://www.ruby-forum.com/u/judofyr)\
**Post date:** [April 9, 2010, 9:39pm UTC](https://www.ruby-forum.com/t/camping-2-0-minature-rails-for-stay-at-home-moms/226063/4 "2010-04-09T21:39:20Z")

</div>

On Apr 9, 2010, at 09:51 , Joel VanderWerf wrote:

> Magnus H. wrote:
> 
> > require “uri”;require “rack”;class Object;def meta\_def m,&b;(class\<\<self;self
> 
> With this post, you have single-handedly restored the ruby-talk signal-to-noise ratio to 2002 levels.

Those were the days, weren’t they?

Now I want to pay Magnus to pit-fight thunk and take care of our 2010  
problem.
