Monthly Archives: May 2013

Rbenv : Careful With That Rubies, Rbenv

This post is about the alternative of RVM (which I presented to you in my last post) – Rbenv. I like the open source world, there are always alternatives…

You’ll ask : “What’s the difference?”. Hmm there are differences:
<<< RVM is tool, designed to bring you listing of all available rubies in the net, downloading and compiling them, switching between them, gemsets.
>>> Rbenv is tool for switching between ruby versions. You download and install the rubies, you decide what tool for dividing the gems to sets should be used.
<<< RVM overrides the ‘cd’ command, in other words when you change directory, the command also ‘looks’ for .rvmrc file in it and executes it. This way you can heave per-project ruby versions.
>>> Rbenv changes the executables in you downloaded gems so if you execute ‘rails’ it looks for .rbenv_version file in the current directory (or in its parents if there is no such file) and uses it to decide the version.
<<< RVM is all in one.
>>> Rbenv has a plugin system and can be set up to be on par with RVM‘s functionality.

If you ask me, which is better, I’ll sincerely answer you – it depends. The important thing is – you should use a tool that works for you, helps you and doesn’t get in your way. For now I prefer Rbenv, because I like the idea of upgrating/downgrating thing through plugins…

Now, this will be a tutorial similar to the one in the post for RVM, I’ll teach you to do the same stuff but with Rbenv.

First of all if you have RVM, remove it the two tools don’t work well together:

rvm implode

Now let us install Rbenv:

git clone git://github.com/sstephenson/rbenv.git ~/.rbenv

This downloads Rbenv in your home’s .rbenv directory.

echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile

This prepends the rbenv commands to your PATH. For Ubuntu and Mint use .profile, for zsh – .zshrc.

echo 'eval "$(rbenv init -)"' >> ~/.bash_profile

This enables shims and auto-completion.Again for Ubuntu and Mint use .profile, for zsh – . You can read more about shims at the Rbenv's github.

exec $SHELL -l

This will restart your shell and the PATH changes will take effect.

We can list the available ruby versions with this:

rbenv versions

We don’s have rubies. So how to install one? I said that Rbenv can only switch between already installed rubies, so you can download ruby binary or source (and compile it) and put it in .rbenv/versions, for example ‘~/.rbenv/versions/1.9.3-p429’. But there is another way. I mentioned earlier, that Rbenv has a plugin system, so we will install a plugin called ruby-build which purpose is to download and install/uninstall rubies.

mkdir -p ~/.rbenv/plugins
cd ~/.rbenv/plugins
git clone https://github.com/sstephenson/ruby-build.git

This is it. To install a plugin, all you have to do is to put it in  ~/.rbenv/plugins. Now lets list the known rubies:

rbenv install --list

Cool. Now to install ruby 1.9.3, patch 429:

rbenv install 1.9.3-p429
rbenv rehash

The second line is important. When you download rubies or executable gems, you will have to run it to update the shim files. Now we have ruby 193-p429. Lets select it globally:

rbenv global 1.9.3-p429

This is the default ruby as of now. You can view it with ‘rbenv global’ or ‘rbenv version’.
Let us continue following my RVM post and to install ruby 2.0.0 with rails:

rbenv install 2.0.0-p195
rbenv rehash
rbenv global 2.0.0-p195
gem install rails
rbenv rehash

Everything is done, now if you run ‘rails -v’ you will have Rails 3.2.13 installed, but if you switch the global ruby with ‘rbenv global 1.9.3-p429’, I won’t have rails installed.

Gemsets… You don’t have them. If you want something similar, you will have to install a plugin.

mkdir -p ~/.rbenv/plugins
cd ~/.rbenv/plugins
git clone git://github.com/jamis/rbenv-gemset.git

So we have the gemset plugin. The idea is that you can include gemsets in a project. Create somewhere a directory for a rails 4 project. Go to this directory and execute:

echo rails4 > .rbenv-gemsets

Now for this folder the gemset is rails4, if you want to use this gemset in another project just navigate to its root folder and execute the above command. That’s it. So now if we are in a folder that is modified this way, we can install rails 4:

gem install rails --version 4.0.0.rc1 --no-ri --no-rdoc

Try it, if you are in the folder the rails version is 4, if you navigate out of it is 3.2. Now the same useful things as in the post for RVM:

  1. To delete a gemset, just delete the .rbenv-gemsets folder.
  2. To use the system ruby just delete the global version file – ~/.rbenv/version or run
    ‘rbenv global system’. If you have problems look at RBENV_VERSION environment variable, you may have to unset it.
  3. To update Rbenv just navigate to ~/.rbenv and pull the newest version through git.
  4. To delete Rbenv just delete the ~/.rbenv  folder and clear your shell’s profile file from Rbenv specific stuff.

Useful Links:

  1. Rbenv site – http://rbenv.org
  2. Ruby Toolbox’s page about Ruby Version Managers – https://www.ruby-toolbox.com/categories/ruby_version_management
  3. Cool post about RVM and Rbenv – http://jonathan-jackson.net/rvm-and-rbenv
  4. Rbenv plugins – https://github.com/sstephenson/rbenv/wiki/Plugins

 

Advertisements

RVM : Set The Controls For The Heart Of Ruby

Many ruby library versions work better with given ruby version. This includes rails versions as well. Another thing is that there are more than one implementation of ruby, for example jruby. If you want to easily switch between implementations and versions you will have to use a dedicated tool. It is easy to install ruby using homebrew or apt-get, but it is not so easy to manage its versions and implementations. Enter RVM – the Ruby Version Manager.

We will begin by installing RVM using our favorite HTTP client – cURL.

curl -L https://get.rvm.io | bash
rvm requirements

Now if you use mac/linux/unix you will have RVM installed. If you use windows (shame on you, and you call yourself a developer) you can’t use RVM (maybe you can using cygwin, who knows), try using PIK instead. By the way there are quite a few installation options on the RVM home site.
The second line may output some instruction you must do before using RVM.

Now we can list our ruby versions using:

rvm list

RVM will tell us that we have no rubies installed. We can check out the available rubies running:

rvm list known

We will see MRI rubies (these are the Matz’s rubies – the C rubies), Jrubies, IronRubies, etc… We are able to install not only different versions but different patches of versions as well. I’m going to install the latest path of ruby 1.93.

rvm install ruby-1.9.3

This will download the ruby source and will compile it. Now if we type

rvm list

We will see our new ruby. With

rvm use ruby-1.9.3

we are already using it. The list command has a legend. We can see that there is something called default ruby. This is the ruby that will be used in all your sessions. Let we set 1.9.3 as our default ruby:

rvm use --default 1.9.3

We have only one ruby now… Let us install one more, ruby 2.0.0, patch 195:

echo progress-bar >> ~/.curlrc
rvm install ruby-2.0.0-p195 -j 3

The first command will add a progress bar when your are downloading a ruby. My machine has four cores and the -j options tells RVM to compile the newly downloaded ruby using 3 of them.
Now we have two ruby versions and we can see them in detail running the ‘rvm list’ command, we can switch between them using the ‘rvm use <ruby-version[-patch]>’ command. The important thing is that if we install gems (these are ruby libraries), they will be installed only for the current ruby. For example let us install rails for ruby 2.0.0:

rvm use 2.0.0
gem install rails

With the first command I want to show you that ‘use’ works only with versions as well (for MRI rubies). The second command installs the rails gem for the current ruby2.0.0. This will install many gems, because Rails has many dependencies (you can read some manga, while waiting).

Now when I run

rails -v

the output is Rails 3.2.13. But if I switch rubies and run it again:

rvm use 1.9.3
rails -v

I have an error. Rails is not installed. So I installed rails only for ruby 2.0.0 and if I want to install rails for 1.9.3, I will have to select ruby 1.9.3 and install it there.

But what if I want to live on the edge! What if I want to use ruby 2.0.0 with rails 4. I don’t want to remove rails 3.2 from ruby 2.0.0, because I am working on some project with it. How can I switch between different versions of one library for a given ruby, how can I have different set of libraries, different gem sets. RVM has gemsets. These are independent spaces filled with gems, they are unlimited for any ruby version. We can see all gemsets for all ruby versions by running:

rvm list gemsets

The output for me is:

rvm gemsets

=> ruby-1.9.3-p429 [ x86_64 ]
   ruby-1.9.3-p429@global [ x86_64 ]
   ruby-2.0.0-p195 [ x86_64 ]
   ruby-2.0.0-p195@global [ x86_64 ]

All ruby versions have a default gemset, the one that is used without specifying gemsets and a global gemset, all the gems in the global gemset are accessible by all other gemsets for the given ruby. Now we are going to create a new gemset for ruby 2.0.0-p195 called rails4. It will contain the Rails 4 gem. Run the following:

rvm use 2.0.0
rvm gemset create rails4
rvm gemset use rails4
rvm gemset list

Now we are using ruby 2.0.0, we’ve created a new gemset called rais4 with the second line, with the third line we told RVM to use the newly created gemset and the last command lists the gemsets of the current ruby. The output of the last command looks like this:

gemsets for ruby-2.0.0-p195 (found in /home/meddle/.rvm/gems/ruby-2.0.0-p195)
   (default)
   global
=> rails4

We can also choose to use a given ruby with a given gemset using ‘rvm use <ruby>@<gemset>’.
OK we are ready to install Rails 4:

gem install rails --version 4.0.0.beta1 --no-ri --no-rdoc

OK, I showed you how to use RVM, how to manage rubies and gemsets. All that is left is to show you a few more useful commands and to call it a post.

  1. You can remove a gemsets using:
    rvm gemset delete <gemset>
  2. You can use the ruby installed on your system (without RVM through for example apt-get) using:
    rvm system
  3. You can update RVM using:
    rvm get stable
  4. You can remove RVM and all the rubies installed with it using:
     rvm implode

So this is it. And one more thing… From this post on, I’m going to have an useful links section at the end of all posts:

Useful Links:

  1. RVM site – https://rvm.io
  2. Ruby Toolbox’s page about Ruby Version Managers – https://www.ruby-toolbox.com/categories/ruby_version_management
  3. Cool post about RVM and Rbenv – http://jonathan-jackson.net/rvm-and-rbenv
  4. My post about cURL link

Now today is 29-th may, the birthday of my dear friend and ex-colleague Icata Banchev, so Happy Birtchday ICO!

Vim : Anywhere With You

Last time I showed you how to manage your Vim plugins with Vundle. Now I want to give you some ideas how to make your configuration portable. Imagine that you are on another machine (some production server for example) and you want your own Vim. Another thing I want to share is my idea for readable Vundle plugin management. So lets start:

  1. The VundleFile. I don’t want to put my plugins in the .vimrc file, I want to keep it clean. So I created a file called VundleFile (or .VundleFile if you want to be hidden) and put it next to my .vimrc configuration. This file looks like that:

    Bundle 'gmarik/vundle'
    Bundle 'tpope/vim-fugitive'
    Bundle 'The-NERD-tree'

    Clean, isn’t it? But the problem is that this file should be sourced somewhere in the .vimrc configuration. So I modified my .vimrc configuration like this:

    au BufRead,BufNewFile VundleFile set filetype=vim
    if filereadable("VundleFile")
        so VundleFile
    endif

    Now if I have a file called “VundleFile” next to the current (.vimrc) file it is sourced and all the Bundles are taken into account. You can do the same thing for a .VundleFile. The command on the first line tells vim to treat the VundleFile as a vimscript source file (when editing it).

  2. Per-project configuration with Vim.
    Put these two lines in your .vimrc file:

    set exrc
    set secure

    Now if you have a .vimrc file in you current folder (for example your project folder) it will be automatically sourced and used. The secure setting will keep you from harm :). You can push this configuration to your git repository and have it anywhere (but you will have to update all the .vimrc files on all machines to have the two lines from this section… Later I will show you how to have fully portable configuration).

  3. Per-project configuration with Vim + per-project plugins.
    The idea is to not only to have a .vimrc configuration in your project folder but to have a .vim folder with all your plugins in it too. Modify the .vimrc configuration of your project to begin with this:

    set nocp
    
    let s:current = expand('%:p:h')
    while s:current != '/'
        if isdirectory(s:current . '/.vim')
            let s:parent = s:current . '/.vim'
            break
        endif
        let s:current = fnamemodify(s:current, ':h')
    endwhile
    
    let s:clean_path = $VIM . '/vimfiles,' . $VIMRUNTIME . ',' . $VIM . '/vimfiles/after'
    let &runtimepath = s:parent . ',' . s:clean_path . ',' . s:parent . '/after'filetype off
    let &runtimepath = &runtimepath . ',' . s:parent . '/bundle/vundle'
    call vundle#rc(s:parent . '/bundle')

    A lot of magic! The first line tells Vim to be Vim and not Vi. It is important; you will use Vundle. The while statement searches for a .vim folder from the current folder up to your root folder and if it finds such folder it saves it in the s:parrent variable (bad name, I know, I’ll fix it some sunny day…). The following two lines clean up the runtime path of vim to contain only the system paths and the found .vim folder. So if you don’t have dedicated .vim folder the one in your home will be used, isn’t this convenient?
    The last three lines setup Vundle to use your project’s .vim folder. So it is important to install Vundle there.
    Now all your plugins will be loaded and installed from this .vim folder. The plugins installed in the home folder won’t affect this configuration. In other words you have absolutely clean vim configuration for the project.

  4. Per-project configuration without depending on the .vimrc located in the home folder.
    This one is easy. Just start vim manually pointing to your project’s .vimrc.

    vim -u .vimrc
  5. Vim as interpreter for Vimscript.
    If you want to try some vimscript commands in something like interpreter. You should start vim like this:

    vim -nNE

    Here is your interpreter. If you want to use the current project configuration for the interpreter:

    vim -nNE -u .vimrc

    If you want to start the interpreter without configuration:

    vim -nNE -u NORC

This is for today, now you are Vim lover. Try this post using the structure in my github – https://github.com/meddle0x53/portable-vim.

Vim : Welcome To The Vundle

Today we are going to talk about Vim. Again…
Vim is your text editor, Vim is your IDE, Vim is everything you need to develop you masterpiece applications. You are skeptical? It is normal. You are used to your comfortable IDE, you are used to click navigation, auto-complete and beautiful menus, why are you going to leave all of that for the dark black window of Vim? Why you use linux/mac instead of windows, why you use chrome/firefox instead of internet explorer, why you are opening you terminal at all… Because you are developer, you want to have control over the things you do and not vice versa…

Vim is not just a text editor, it can be extended by plugins. And yes I know that you think that means putting strange files at strange places and waiting for the magic to happen after the restart.

Vim has a plugin that does the plugin management for you. It is called Vundle. It has alternatives and I’ll talk about them some sunny day, but for now let’s talk about Vundle.

You can go to the its github site – https://github.com/gmarik/vundle. There you’ll find instructions  for installing and using it. But I’m going to explain some of these instructions to you, so:

  1. Go to your $HOME/.vim folder (cd ~/.vim).
  2. Create a folder called bundle, if it doesn’t already exist (mkdir bundle).
  3. Navigate to the bundle directory (cd bundle).
  4. If you don’t have git, install it (sudo apt-get install git / brew install git). Execute the following command:
    git clone https://github.com/gmarik/vundle.git
  5. Vundle is downloaded. Now edit your vimrc file (vim ~/.vimrc).
     set nocp                       " Vim is not Vim if it is Vi compatible
     filetype off                   " required!
    
     set rtp+=~/.vim/bundle/vundle/
     call vundle#rc()  
     Bundle 'gmarik/vundle' 
     filetype plugin indent on     " required!
  6. Now save the file and exit. Lets examine the vimrc script.
    – The first two line make so that Vim can handle working with Vundle; We should be VIm, not Vi and the FileType event will be turned off for now.
    – The third line adds the Vundle plugin to the runtime path.
    – The fourth line turns on Vundle, by calling the ‘rc’ function defined in the plugin.
    – From here on, we can add bundles using the Bundle command.
    – After all the bundles (plugins) are listed we turn on the FyleType event again. But with this particular command we tell vim to load the plugins located in the ftplugin directories related to the file type of the file we open for editing.
  7. You can add bundles for plugins located at github by adding Bundle ‘<user>/<project>’
  8. You can add bundles in normal no-github repositories by adding Bundle ‘<url>’
  9. You can add the bundles from the https://github.com/vim-scripts repository with
    Bundle ‘<plugin_name>’
  10. :BundleInstall – installs all the Bundles specified in your vimrc that are not already installed.
  11. :BundleInstall! – installs all the Bundles specified in your vimrc that are not already installed and updates these which are installed but can be updated.
  12. :BundleList – lists all the bundles that are installed.
  13. :BundleSearch – can be used to list all the known bundles or to search for bundles using a search phrase.

If you decide to use vim as your primary text/source code editor, you should try Vundle. Later in various posts I’ll use different Vim plugins, that you can easily install using Vundle.

Df & Du : In Too Deep, Can’t Touch The Bottom

In this post I’ll show you how to explore your hard disk and memory through the command line.

  1. The first command I’ll show you is df‘ (disk free):
    `df -h` :  Displays the sizes of the mounted file systems in human readable format. Here is the output on my machine:
    Filesystem Size Used Avail Use% Mounted on
    /dev/sda5 7.6G 5.9G 1.3G 83% /
    udev 3.8G 12K 3.8G 1% /dev
    tmpfs 1.6G 1.1M 1.6G 1% /run
    none 5.0M 0 5.0M 0% /run/lock
    none 3.8G 13M 3.8G 1% /run/shm
    none 100M 16K 100M 1% /run/user
    /dev/sda6 54G 24G 28G 46% /home
    /dev/sda2 54G 48G 5.4G 90% /media/5CCAC272CAC247CA
    

    Easy to understand. Try running only `df`, the result will be similar but the metrics will be different.
    `df –total -h` This command is the same as the above, but will show you the total size, used and available of all your storage media.

    Filesystem Size Used Avail Use% Mounted on
    /dev/sda5 7.6G 5.9G 1.3G 83% /
    udev 3.8G 12K 3.8G 1% /dev
    tmpfs 1.6G 1.1M 1.6G 1% /run
    none 5.0M 0 5.0M 0% /run/lock
    none 3.8G 6.3M 3.8G 1% /run/shm
    none 100M 16K 100M 1% /run/user
    /dev/sda6 54G 24G 28G 46% /home
    /dev/sda2 54G 48G 5.4G 90% /media/5CCAC272CAC247CA
    total 124G 77G 44G 65%

    `df -a` This will show you the sizes of the dummy file systems like ‘/proc’.
    Try executing `df –total -ah`

  2. The second command is ‘du’ (disk usage). Du shows the sizes of directories and their sub-trees. For example navigate to your home directory and type `du`. This will print something very long and hard to read. Try the ‘du’ command with a small directory tree.
    `du -h` Like the ‘df’ version – human readable. Here is an example:
    du -h Music/smerch/
    
    530M Music/smerch/segment 3
    282M Music/smerch/segment 1
    269M Music/smerch/segment 5 alt
    441M Music/smerch/segment 4
    610M Music/smerch/segment 2
    2.1G Music/smerch/
    

    Try it yourself.
    `du -ah` This adds the sizes of each file in the folder passed and it sub-trees. The ‘-a’ option stands for all.
    `du -hs` This will list the sizes only of the current directory and its direct sub-directories.
    – You can pass globs to ‘du’ to filter its output.
    `du -sk .[!.]* *| sort -n` Now this is something interesting. It shows the sizes of all the direct sub-folders of the current folder, including the hidden ones and the output is sorted by these sizes. The size metric is kilobyte. The ‘-s’ option tells ‘du’ to show the sizes only of the direct sub-folders and the current folder. The ‘-k’ option tells ‘du’ that it should display the sizes in kilobytes (you can use -h or -m instead). The globs .[!.]* * specify all the hidden folder names and all the folder names respectively. The result is then passed to ‘sort’. You can pass the ‘-r’ option to ‘sort’ to reverse the output.
    – You can specify the maximum depth of the sub-directory trees – `du -h –max-depth=1`. The -d option is a synonym of –max-depth.

     If you want to explore more use man or info with df and du.

  3. This is not included in the title, but I’m going to show you the ‘free’ command too.
    `free` Displays information for the memory (used/available/total) in kilobytes (-b will display the same information in bytes, -m in megabytes and -g in gigabytes).
    `free –total` Displays total summary for physical memory + swap space.
    `free -s 5` Now free will begin displaying memory information and it will be updated on every 5 seconds.

REST : RESTin’ in the RESTful World – part 1

Today I’m going to present to you the RESTful architecture. The concept is simple but often misunderstood. I’m a big fan of the idea, because it gives us both freedom and simplicity by just using the HTTP protocol.

REST stands for “REpresentational State Transfer” and is introduced in 2000 by Roy Fielding in his doctoral dissertation. I know quite a few people which think of REST as just using HTTP GET and POST requests to modify and read resources in given format. This is not REST, this is some kind of custom communication API. I was one of these people until I chose to read some books and articles for a change and it turned out to be quite refreshing… I’ll tell you about the RESTful architecture as I see it through my mind.

Imagine that the Web is an Universe. Universe composed of resources. These resources have unique identifiers and can be viewed through many different representations. For example in a list of comments, stored somewhere in the Web we have many comment resources. Every comment resource has its own URI (identifier) that points to it. The comment resource consists of an author and comment body, maybe some database ID and a time-stamp providing information about when the resource was last edited. We can add some metadata to this resource that provides information about the maximum acceptable length of a comment body…

Now we can view these resources in some representation. For example the list of the comment resources is stored in a database, but we won’t download the database file in its raw format, we will present an HTML page showing the comments, or we will return XML representation of the list, or JSON, or YAML, or some PDF. These are the representations. The server provides one or more representations of the resource for example HTML, JSON and XML. We can tell the server which representation we want to use. For example we can navigate with the browser to the URL http://forum-meddlings.rhcloud.com/comments and this will render the comment list in its HTML representation. If we navigate to http://forum-meddlings.rhcloud.com/comments.json, we will see the JSON representation of the list. Let’s use cURL:

  • curl -i http://forum-meddlings.rhcloud.com/comments
    

    This will retrieve the comment list in HTML format, the Content-Type response header value is ‘text/html;charset=utf-8’.

  • curl -i http://forum-meddlings.rhcloud.com/comments.json
    

    Now we see a JSON array containing the comments as JSON objects, the Content-Type response header value is ‘application/json;charset=utf-8’.

  • curl -i -H "Accept: application/json" \
    http://forum-meddlings.rhcloud.com/comments
    

    Again we see a JSON array containing the comments as JSON objects, the Content-Type response header value is ‘application/json;charset=utf-8’. We used the Accept request header to tell the server that we accept only JSON response.

The above conversations with the server are interesting. We want the server to Transfer to us the current State of the resource identified by the URL. We negotiate with the server for the REpresentation of the resource. This content negotiation is done by adding a format at the end of the URL or by setting the Accept request header. If the server doesn’t recognize the format it can send us HTTP 406 response (not acceptable).

We saw how we are able to view given resource state in a given representation, it is simple – we know where the resource is accessible via its URL and we request it from the server in given format via the request. But what if we want to create new resource or delete existing one or edit a resource.

The HTTP protocol has its methods (verbs). You all know about GET and POST, and maybe you know of PUT, DELETE, HEAD, TRACE and OPTIONS…

I’m going to introduce you to the REST CRUD (CREATE, READ, UPDATE, DELETE). We will use POST for creation, GET for reading, PUT for updating and DELETE for deleting resources. It is important to understand the difference between PUT and POST.
POST creates resources. It POSTs a new resource to a collection of resources; when you execute POST you don’t know what the URL of the new resource will be.
For example you have http://somewhere.com/resources and you POST a new resource to this URL, when the new resource is created it is given a new unique URL http://somwhere.com/resource/5. Now we can use PUT to update the resource located at this URL. PUT knows the URL of the resource it modifies.
So POST adds a new resource to a resource collection, creates resources, and PUT updates the resource data located at existing an URL.

Another thing about the HTTP verbs. GET, PUT and DELETE are idempotent. This means that if I execute the same PUT request one time or 100 times the result will be the same. Think about it… We modify the resource at http://somwhere.com/resource/5 setting the value ‘foo’ to ‘bar’, if we execute the same request 100 times the result we’ll be the same as the first time, a resource with attribute ‘foo’ set to ‘bar’. The same is true for DELETE – you can delete the resource one time or 100 times, in the end it will be deleted, the same as the first time. GET is reading, the same every time.
POST is another story if we POST the same resource data 5 times in the http://somewhere.com/resources collection we will have 5 different resources with the same data. Again the difference between POST and PUT, POST creates new resources with new IDS, new URLs…

I think we are ready to communicate with our RESTful API. We will create a new resource, then we will read it, we will update it and delete it. The API is simple:
– Here we have a collection of comment resources – http://forum-meddlings.rhcloud.com/comments
– Every comment resource has unique id and is located at http://forum-meddlings.rhcloud.com/comment/<id>
– When we read resources from the collection we can use their IDs to manipulate them.
– My application provides us we two representations – JSON and HTML, you can play with the HTML representation through your browser.
– Every comment has two mandatory fields – ‘author’ and comment ‘body’.

      1. Lets create a new comment; we will POST to http://forum-meddlings.rhcloud.com/comments a new comment represented as JSON data.
        We will tell the server how to parse this data by setting the request’s Content-Type header to ‘application/json’ and we will want the newly resource in JSON format, so the Accept header will be set to ‘application/json’ too:

        curl -i \
          -H "Accept: application/json" \
          -H "Content-Type: application/json" \
          -d '{"author": "meddle", "body": "My new comment!"}' \
          http://forum-meddlings.rhcloud.com/comments

        We created the new comment! Here is the response:

        HTTP/1.1 200 
        Date: Tue, 14 May 2013 13:27:56 GMT
        Server: Apache/2.2.15 (Red Hat)
        X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.17
        Content-Length: 69
        Status: 200
        Content-Type: application/json;charset=utf-8
        Vary: Accept-Encoding
        
        {"id":5,"author":"meddle","body":"My new comment!","time":1368538076}

        We can see that the id of the new comment is 5.

      2. Now its time to read the new comment using its id – its URL will be http://forum-meddlings.rhcloud.com/comment/5
        Request:
        curl -i \
          -H "Accept: application/json" \
          http://forum-meddlings.rhcloud.com/comment/5
        
        Response:
        HTTP/1.1 200 
        Date: Tue, 14 May 2013 13:30:43 GMT
        Server: Apache/2.2.15 (Red Hat)
        X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.17
        Content-Length: 69
        Status: 200
        Content-Type: application/json;charset=utf-8
        Vary: Accept-Encoding
        
        {"id":5,"author":"meddle","body":"My new comment!","time":1368538076}

        So we’ve created a new comment and we know its location, it is persisted there.

      3. Let’s edit our new comment:
        Request:
        curl -i \
          -H "Accept: application/json" \
          -H "Content-Type: application/json" \
          -d '{"author": "meddle", "body": "My new comment! Edited!"}' \
          -X PUT \
          http://forum-meddlings.rhcloud.com/comment/5
        Response:
        HTTP/1.1 200 
        Date: Tue, 14 May 2013 13:37:10 GMT
        Server: Apache/2.2.15 (Red Hat)
        X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.17
        Content-Length: 77
        Status: 200
        Content-Type: application/json;charset=utf-8
        Vary: Accept-Encoding
        
        {"id":5,"author":"meddle","body":"My new comment! Edited!","time":1368538630}
      4. Now after updating our comment why don’t we see the whole list:
        Request:
         curl -i \
          -H "Accept: application/json" \
          http://forum-meddlings.rhcloud.com/comments
        Response:
        HTTP/1.1 200
        Date: Tue, 14 May 2013 13:44:00 GMT
        Server: Apache/2.2.15 (Red Hat)
        X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.17
        Content-Length: 288
        Status: 200
        Content-Type: application/json;charset=utf-8
        Vary: Accept-Encoding
        
        [{"id":1,"author":"meddle","body":"First","time":1368526814},
        {"id":2,"author":"meddle","body":"This is from the JSON API!","time":1368526899},
        {"id":3,"author":"Some Gangsta","body":"Yo man!","time":1368530204},{"id":5,"author":"meddle","body":"My new comment! Edited!","time":1368538630}]
      5. Now we can delete our comment:
        Request:
        curl -i \
          -H "Accept: application/json" \
          -X DELETE 
          http://forum-meddlings.rhcloud.com/comment/5
        
        Response:
        HTTP/1.1 204 
        Date: Tue, 14 May 2013 13:48:22 GMT
        Server: Apache/2.2.15 (Red Hat)
        X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.17
        Status: 204
        Content-Length: 0
        Content-Type: text/plain
      6. So if try to read the deleted comment, we will receive HTTP 404 – Not Found:
        Request:
         curl -i \
          -H "Accept: application/json" \
          http://forum-meddlings.rhcloud.com/comment/5
        
        Response:
         HTTP/1.1 404
         Date: Tue, 14 May 2013 13:49:49 GMT
         Server: Apache/2.2.15 (Red Hat)
         X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.17
         Content-Length: 30
         Status: 404
         Content-Type: application/json;charset=utf-8
        
        {"error":"Comment not found."}

This was one long post… But there is more : in the second part we will see the server implementation in Sinatra. Bye for now.

CURL : All I Ever Wanted Was Before My Eyes (I’m talking about HTTP client)

The program cURL is a capable HTTP client. This means we can do a variety of HTTP queries through the command line and test our services with ease, using cURL. It’s OK for testing purposes, but sometimes you will need to parse the response and do something with it, in that case you should use something more complex… Anyway lets start:

  1. Requesting a page:
    curl http://forum-meddlings.rhcloud.com

    This executes a HTTP GET request to the given URL, simple and working.

  2. Requesting a page and viewing it’s response headers:
    curl -s -D - http://forum-meddlings.rhcloud.com -o /dev/null

    -s (–silent) Silent or quiet mode. Don’t show progress meter or error messages.
    # -D (–dump-header) <file> Writes the protocol headers to the specified file (if no file is specified to the output).
    # -o (–output) <file> Writes the response to the file specified.
    So we are dumping the headers to the console output and the response to the black hole of nothingness. This is helpful if we want to explore only the headers of the response, if you want to view both the header and the body of the response, just  skip the -o option. Another way of doing this is:

    curl -i  http://forum-meddlings.rhcloud.com

    # -i (–include) Include the HTTP-header in the output.

  3. Request with a different HTTP method. Posting data through the POST verb:
    curl -i -X POST -d "author=meddle&body=BLAME" \
    http://forum-meddlings.rhcloud.com/comments
    

    Now this posts to the given URL the data. I separated the command to be on two lines for readability…
    # -X (–request) Specifies the request method to use when communicating with the server.
    # -d (–data) The data for the request, in the example we have POST parameters.

  4. Passing request headers:
    curl -i -H "X-HTTP-Method-Override: PUT" -X POST -d "body=Yohohohoho" \
        http://forum-meddlings.rhcloud.com/comment/1

    We changed the HTTP method through the method override header.
    # -H (–header) Adds a request header.

    We can add as many headers as we want:

    curl -i  \
        -H "X-HTTP-Method-Override: PUT" \
        -H "Acept: application/json" \
        -H "User-Agent: Mozilla/5.0 AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405" \
        -X POST -d "body=Now we play" \
        http://forum-meddlings.rhcloud.com/comment/1
  5. OK, I saw the comments. Working with cookies is interesting topic for you?
    Lets log in into our http://www.abv.bg account :). If you don’t have any, just sign up. Now we are going to use cURL to log in:

    curl -c cookiefile i -X POST \
      -d "username=<your-user-name>&password=<your-password>&host=mail01.abv.bg&service=mail" \
      https://passport.abv.bg/app/profiles/servicelogin

    What we’ve done so far?
    – We’ve posted our credentials (and additional data, that I got from the HTML form tag of the login page) to the https://passport.abv.bg/app/profiles/servicelogin’ URL and told cURL that our cookie jar is ‘cookiefile’.
    # -c (–cookie-jar) Tells cURL to start its cookie engine and write cookies to the given file after the request
    – Now we can use this ‘cookiefile’ to send cookies to the site.
    – The response page of the request executes a javascript, replacing the location with a new URL. This is the URL we have to request to get into the home page.

    curl -b cookiefile -L -i \
      http://mail50.abv.bg/app/servlet/plogin?s=<some-id-from-the-response>

    Now we should be able to view the markup of our inbox.
    # -b (–cookie) Tells cURL a file to read cookies from and start its cookie engine, or if it isn’t a file it will pass on the given string. -b name=var works and so does -b cookiefile.
    # -L (–location) Tells cURL to follow redirect location; The request above returns a 302 response and cURL follows the new location.

    It is common to use something like this to write and read from the cookie file for the same request:

    curl -b cookies -c cookies http://www.somewhere.com

So this is how you can use cURL as HTTP client, you can type ‘man curl’ to see all the other options it supports. For example cURL can be used as FTP or SFTP client too.