---
title: Camping.goes :Camping
teaser: An introduction to the Ruby Camping web framework.
tags: web,ruby,rubedo
author: Eric Mill
published_on: 2007-01-15
---

Many in the Rails community have at least heard of [Camping], a microframework
by [why the lucky stiff][why].  It was only recently that I discovered that it
is genuinely useful, even inspiring, for small applications.

I'm currently at work on a tiny application called [Rubedo], which offers a tiny
Icecast source client, with an also-tiny web front-end.  I'm writing it in Ruby,
and so I began to do the front-end in Rails, just to get it working, and this
was fine.  But this application is small&#8212;in its entire life I can't see it
having more than 2 models, and right now it only has 1.  Since I'm a RESTful
man, the same applies to controllers.  Furthermore, this app needs to be light
and portable, and looking at it from that perspective, Rails is an atom bomb.  I
feel strongly about the dropping of the atomic bomb on Hiroshima and Nagasaki,
so when a coworker mentioned that this might be a good excuse to try out
Camping, I suspected this could be a good fit.

So what is Camping, and why is it so great?

The driving idea behind Camping, as translated from why's [beautiful hummingbird
language][hummingbird], is to have your entire <abbr title="Model View
Controller">MVC</abbr> application in one file.  Failing that, in as few files
as possible.  First, I'll give a small code example, stolen [right from
why][stolen-why].  Then, bullet points.

```ruby
require 'camping'

Camping.goes :Blog

module Blog::Models
  class Post < Base; belongs_to :user; end
  class Comment < Base; belongs_to :user; end
  class User < Base; end
end

module Blog::Controllers
  class Index < R '/'
    def get
      @posts = Post.find :all
      render :index
    end
  end
end

module Blog::Views
  def layout
    html do
      body do
        self << yield
      end
    end
  end

  def index
    for post in @posts
      h1 post.title
    end
  end
end
```

* For models, Camping uses ActiveRecord, so your model code is nearly identical
  to what it would be in Rails.
* For views, Camping uses [Markaby], so views are written entirely in Ruby and
  frighteningly compact.  As you can see, there's layouts, and don't worry,
  there's also partials.
* For controllers, Camping uses carefully calculated insanity to intermingle
  your controllers and routes.  This is certainly the most novel part of Camping
  and the aspect that most differs from Rails, so best practices with it are
  currently up in the air for me.  It's a land of experimentation.
* [SQLite] is the database backend.  SQLite satisfies both halves of its name
  extremely well, and doesn't require any user authentication or background
  server process.  You should think about using SQLite all the time, including
  right now.
* It runs by typing camping blog.rb.  You might also use -d blog.db as a
  parameter to specify the DB file.  Then, visit http://localhost:3301 in your
  browser.

But wait.  Routes??

Your controller class inherits from an anonymous class constructed by calling R
with a regular expression.  So, to make a more nimble route, like to fetch and
display a Post by id:

```ruby
class Posts < R '/posts/(\d+)'
  def get(id)
    @post = Post.find id
    render :post
  end
end
```

But wait.  Javascript?? <abbr title="Cascading Style Sheets">CSS</abbr>??

Assuming it's as simple as your application is, just include it with the rest.
Yes:

```ruby
class Stylesheet < R '/blog.css'
  def get
    @headers['Content-Type'] = 'text/css'
    "body {fist: face}"
  end
end
# in your view
link :href => R(Stylesheet), :rel => 'stylesheet', :type => 'text/css'
```

But wait.  time\_ago\_in\_words??

I couldn't live without that function either.  But you can just include in stuff
like that, you know.  It's your app, your dependencies.  Like so:

```ruby
require 'action_view/helpers/date_helper.rb'
module Blog
  include ActionView::Helpers::DateHelper
end
```

I have absolutely no problem working like this.  I don't foresee my application,
even with an upcoming User model and account system, growing beyond the point
where I will get antsy about staying in Camping.  Having my whole app in front
of me while I work is a surprisingly gratifying experience.  Working on it feels
more like sculpting a statue, or rubbing a weak, newly born mouseling into life.

I was attracted to Rails by its simplicity and how much you could do in a small
amount of code.  In fact, it seriously eroded my respect in the <abbr title="PHP
HyperText Preprocessor">PHP</abbr> and Java languages, and frameworks based off
of them.  After making the decision to build my radio frontend in Camping, and
working in it for a week, I feel almost the same degree of attraction.  With it
does not come any loss of respect for Rails, as Camping just isn't appropriate
for applications above a certain low bar of complexity.  It would be only a step
or two above trivial to port an application outgrowing its Camping gear into a
full Rails application.  I think that you would remember the experience fondly.

Yet you may surprise yourself by how complex your code can get, while still
being reducible to something good-looking in a Camping jacket.  I've been
steadily adding more features to my application, and after each one follows a
brief inner (and outer) struggle to make it work cheaply, tersely, and
elegantly.  The culture of Camping demands this, and I'm a better person for it.

Insightfully, why created other, [more realistic examples][examples] of Camping
that helped me a great deal in realizing more of Camping's power.  Look over
them, maybe even download and run them, to see it at work.  Remember though,
that Camping, in the end, only attempts to fulfill one overarching and all
consuming purpose:

![''](http://images.thoughtbot.com/ui/2007-1-14-camping-whale-bounce.png)

[Camping]: http://code.whytheluckystiff.net/camping/
[examples]: https://github.com/camping/camping/tree/master/examples
[hummingbird]: http://redhanded.hobix.com/bits/campingAMicroframework.html
[Markaby]: http://code.whytheluckystiff.net/markaby/
[Rubedo]: http://rubyforge.com/projects/rubedo
[SQLite]: https://www.sqlite.org/
[stolen-why]: https://github.com/camping/camping#a-camping-skeleton
[why]: http://viewsourcecode.org/why/
