# Getting Started¶ ↑

You’ll need Ruby Gems to get camping. Install camping like so:

    gem install camping

Start a new text file called camp.rb. Here’s what you put inside:

    require 'camping'
    Camping.goes :Nuts

Save it. Then, open a command prompt in the same directory. You’ll want to run:

    $ camping

And you should get a message which reads:

    ** Camping running on 0.0:3301.

This means that right now The `Camping` Server is running on port 3301 on your machine. Open your browser and visit localhost:3301/.

Your browser window should show:

    Camping Problem!

    / Not found

No problem with that. The `Camping` Server is running, but it doesn’t know what to show. Let’s tell them.

## Hello clock¶ ↑

So, you’ve got `Camping` installed and it’s running. Keep it running. You can edit files and The `Camping` Server will reload automatically. When you need to stop the server, press Control-C.

Let’s show something. At the bottom of camp.rb add:

    module Nuts::Controllers
      class Index < R '/'
        def get = Time.now.to_s
      end
    end

Save the file and refresh the browser window. Your browser window should show the time, e.g.

    Sun Jul 15 12:56:15 +0200 2007

## Enjoying the view¶ ↑

The `Camping` microframework allows us to separate our code using the MVC (Model-View-Controller) design pattern. Let’s add a view to our Nuts application. Replace the `module Nuts::Controllers` with:

    module Nuts::Controllers
      class Index < R '/'
        def get
          @time = Time.now
          render :sundial
        end
      end
    end

And below it add:

    module Nuts::Views
      def layout
        html do
          head do
            title { "Nuts And GORP" }
          end
          body { self << yield }
        end
      end

      def sundial = p "The current time is: #{@time}"
    end

Save the file, refresh your browser window and it should show a message like:

    The current time is: Sun Jul 15 13:05:41 +0200 2013

And the window title reads “Nuts And GORP”.

Here you can see we call `render :sundial` from our controller. This does exactly what it says, and renders our `sundial` method. We’ve also added a special method called `layout` which `Camping` will automatically wrap our sundial output in. If you’re familiar with HTML, you’ll see that our view contains what looks HTML tag names. This is Markaby, which is like writing HTML using Ruby!

Soon enough, you’ll find that you can return anything from the controller, and it will be sent to the browser. But let’s keep that for later and start investigating the routes.

## Routes¶ ↑

You probably noticed the weird `R '/'` syntax in the previous page. This is an uncommon feature of Ruby that is used in our favorite microframework, to describe the routes which the controller can be accessed on.

These routes can be very powerful, but we’re going to have look at the simplest ones first.

    module Nuts::Controllers
      class Words < R '/welcome/to/my/site'
        def get = "You got here by: /welcome/to/my/site"
      end

      class Digits < R '/nuts/(\d+)'
        def get(number) = "You got here by: /nuts/#{number}"
      end

      class Segment < R '/gorp/([^/]+)'
        def get(everything_else_than_a_slash) = "You got here by: /gorp/#{everything_else_than_a_slash}"
      end

      class DigitsAndEverything < R '/nuts/(\d+)/([^/]+)'
        def get(number, everything) = "You got here by: /nuts/#{number}/#{everything}"
      end
    end

Add this to `camp.rb` and try if you can hit all of the controllers.

Also notice how everything inside a parenthesis gets passed into the method, and is ready at your disposal.

### Simpler routes¶ ↑

This just in:

    module Nuts::Controllers
      class Index
        def get = "You got here by: /"
      end

      class WelcomeToMySite
        def get = "You got here by: /welcome/to/my/site"
      end

      class NutsN
        def get(number)= "You got here by: /nuts/#{number}"
      end

      class GorpX
        def get(everything_else_than_a_slash) = "You got here by: /gorp/#{everything_else_than_a_slash}"
      end

      class NutsNX
        def get(number, everything) = "You got here by: /nuts/#{number}/#{everything}"
      end
    end

Drop the `< R`-part and it attempts to read your mind. It won’t always succeed, but it can simplify your application once in a while.

## Modeling the world¶ ↑

You can get pretty far with what you’ve learned now, and hopefully you’ve been playing a bit off-book, but it’s time to take the next step: Storing data.

Let’s start over again.

    Camping.goes :Nuts

    module Nuts::Models
      class Page < Base
      end
    end

Obviously, this won’t do anything, since we don’t have any controllers, but let’s rather have a look at what we do have.

We have a model named Page. This means we now can store wiki pages and retrieve them later. In fact, we can have as many models as we want. Need one for your users and one for your blog posts? Well, I think you already know how to do it.

However, our model is missing something essential: a skeleton.

    Camping.goes :Nuts

    module Nuts::Models
      class Page < Base
      end

      class BasicFields < V 1.0
        def self.up
          create_table Page.table_name do |t|
            t.string :title
            t.text   :content
            # This gives us created_at and updated_at
            t.timestamps
          end
        end

        def self.down
          drop_table Page.table_name
        end
      end
    end

Now we have our first version of our model. It says:

    If you want to migrate up to version one,
      create the skeleton for the Page model,
      which should be able to store,
        "title" which is a string,
        "content" which is a larger text,
        "created_at" which is the time it was created,
        "updated_at" which is the previous time it was updated.

    If you want to migrate down from version one,
      remove the skeleton for the Page model.

This is called a migration. Whenever you want to change or add new models you simply add a new migration below, where you increase the version number. All of these migrations builds upon each other like LEGO blocks. Each new Migrations must have different class’s names, is a good idea name migration’s explicit. For example:

    class AddTagColumn < V 1.1
      def self.change
       add_column Page.table_name, :tag, :string
       Page.reset_column_information
      end
    end

Now we just need to tell `Camping` to use our migration. Write this at the bottom of camp.rb

    def Nuts.create
      Nuts::Models.create_schema
    end

When The `Camping` Server boots up, it will automatically call `Nuts.create`. You can put all kind of startup-code here, but right now we only want to create our skeleton (or upgrade if needed). Start The `Camping` Server again and observe:

    $ camping camp.rb
    ** Starting Mongrel on 0.0.0.0:3301
    -- create_table("nuts_schema_infos")
       -> 0.1035s
    ==  Nuts::Models::BasicFields: migrating ===================================
    -- create_table(:nuts_pages)
       -> 0.0033s
    ==  Nuts::Models::BasicFields: migrated (0.0038s) ==========================

Restart it, and enjoy the silence. There’s no point of re-creating the skeleton this time.

Before we go on, there’s one rule you must know: Always place your models before your migrations.

## Using our model¶ ↑

Let’s explore how our model works by going into the console. The console is good way to familiarize with your models. Test your models adding some data by bare hand before addin it to the application.

    $ camping -C camp.rb
    ** Starting console
    >>

Now it’s waiting for your input, and will give you the answer when you press Enter. Here’s what I did, leaving out the boring answers. You should add your own pages.

    >> Page = Nuts::Models::Page

    >> hiking = Page.new(:title => "Hiking")
    >> hiking.content = "You can also set the values like this."
    >> hiking.save

    >> page = Page.find_by_title("Hiking")
    => #<Nuts::Models::Page id: 1, ... >
    >> page = Page.find(1)
    => #<Nuts::Models::Page id: 1, ... >
    >> page.title
    >> page.content
    >> page.created_at
    >> page.updated_at

    >> Page.find_by_title("Fishing")
    => nil

    ## Page.create automatically saves the page for you.
    >> Page.create(:title => "Fishing", :content => "Go fish!")

    >> Page.count
    => 2

Now I have two pages: One about hiking and one about fishing.

## Wrapping it up¶ ↑

Wouldn’t it be nice if we could show this wonderful our pages in a browser? Update camp.rb so it also contains something like this:

    module Nuts::Controllers
      class Pages
        def get
          # Only fetch the titles of the pages.
          @pages = Page.all(:select => "title")
          render :list
        end
      end

      class PageX
        def get(title)
          @page = Page.find_by_title(title)
          render :view
        end
      end
    end

    module Nuts::Views
      def list
        h1 "All pages"
        ul do
          @pages.each do |page|
            li do
              a page.title, :href => R(PageX, page.title)
            end
          end
        end
      end

      def view
        h1 @page.title
        self << @page.content
      end
    end

Here we meet our first helper:

    R(PageX, page.title)

This is the reversed router and it generates a URL based on a controller. R takes the controller you want to link to, followed by the router parameters. . Instead of typing:

    :href=>'/welcome/to/my/site'

You can let `Camping` do the hard work for you.

    :href=>R(Words)

If the route would have some parameter, you shall write like this:

    :href=>R(WordsX,'someword')

`Camping` ships with a few, but very useful, helpers, and you can easily add your owns. Have a look at Camping::Helpers for how you use these.

There’s a lot of improvements you could do here. Let me suggest:

- Show when the page was created and last updated.

- What happens when the page doesn’t exist?

- What should the front page show?

- Allow or disallow authenticated users.

- Add a layout.

- Jazz it up a bit.

Helpers can work generating Markaby’s code. You could write a helper for show some kind of data and call it from your views (Add a layout).

## The last touch¶ ↑

We have one major flaw in our little application. You can’t edit or add new pages. Let’s see if we can fix that:

    module Nuts::Controllers
      class PageX
        def get(title)
          if @page = Page.find_by_title(title)
            render :view
          else
            redirect PageXEdit, title
          end
        end

        def post(title)
          # If it doesn't exist, initialize it:
          @page = Page.find_or_initialize_by_title(title)
          # This is the same as:
          # @page = Page.find_by_title(title) || Page.new(:title => title)

          @page.content = @input.content
          @page.save
          redirect PageX, title
        end
      end

      class PageXEdit
        def get(title)
          @page = Page.find_or_initialize_by_title(title)
          render :edit
        end
      end
    end

The core of this code lies in the new `post` method in the PageX controller. When someone types an address or follows a link, they’ll end up at the `get` method, but you can easily create a form which rather sends you to the `post` when submitted.

There are other names you can use, but they won’t always work. So for now, don’t be fancy and just stick to `get` and `post`. We’ll show you how this really works later.

You might also notice that we use `@input.content`. The `@input`-hash contains any extra parameters sent, like those in the forms and those in the URL (`/posts?page=50`).

Here’s an `edit`-view, but you can probably do better. See if you can integrate all of this with what you already have.

    module Nuts::Views
      def edit
        h1 @page.title
        form :action => R(PageX, @page.title), :method => :post do
          textarea @page.content, :name => :content,
            :rows => 10, :cols => 50

          br

          input :type => :submit, :value => "Submit!"
        end
      end
    end

## Phew.¶ ↑

You’ve taken quite a few steps in the last minutes. You deserve a break. But let’s recap for a moment:

- Always place `Camping.goes :App` at the top of your file.

- Every route ends at a controller, but …

- … the controller only delegates the work.

- `@input` contains the extra parameters.

- The views are HTML disguised as Ruby.

- They can access the instances variables (those that starts with a single at-sign) from the controller.

- The models allows you to store all kinds of data.

- Place your models before your migrations.

- Helpers are helpful.

If you wanna dive deep, stay reading for a more extended tutorial step by step…

Enjoy the code