About MongoDB

Task:

Clone the code for this session:

    $ git clone https://github.com/code61/mongo1.git

In this session we will be using a database - a specialised piece of software for storing and retrieving data. Databases become important when you have large amounts of data, which you want to be able to access quickly and which you want to keep consistent.

In the session we will be using two different, but related, pieces of software:

  • MongoDB the database.
  • Mongoid a ruby library that we will use to interface with MongoDB.

MongoDB is one of many different databases that we could have chosen. We went with MongoDB because it is fairly straight-forward to configure and quick to get going with. It is also fairly popular in the web community at the moment.

MongoDB is a NOSQL, or document-based, database. In the past, the more traditional style SQL, or relational, databases were used in most applications. NOSQL databases have risen in popularity in the last year or two, in part due to their ability to offer increased performance in certain common scenarios, by allowing developers to bend the rigid SQL database structures. We will go into this in slightly more depth later in the course. For the time being, with data we’re storing in the next few sessions it won’t make much difference whether our db is SQL or NOSQL.

Starting MongoDB

In order to use MongoDB in a ruby project, it first needs to be running on your computer. The command for this is

$ mongod

You will need to keep this command line open and continue the instructions in a new one.

By default mongo will run on localhost:28017. If you visit that link in your browser you should see a mongo stats page.

Using it in ruby

To interface with MongoDB from ruby we will be using the Mongoid gem. You should have installed the gem already, but if not,

$ gem install mongoid

should do the trick.

We then need to set some configuration options in our ruby project. Among other things this tells the project which of the mongodb databases on your computer to use - usually you’d want each project to have its own database. The following configuration options should go in a mongoid.yml file:

development:
  sessions:
    default:
      hosts:
        - localhost:27017
      database: mongo_examples
  options:
    raise_not_found_error: false

You then need to include the following code in your app.rb (or similar) file:

require 'mongoid'
require 'json'

Mongoid.load!("mongoid.yml", :development)

We’ve seen the require statements before - they just tell ruby that we’d like to use the mongoid library (and also json). The line Mongoid.load!("mongoid.yml", :development) tells mongoid where to find the configuration options. The :development bit refers to our environment - you will probably want to have different configuration options when you’re deploying your app to heroku; mongoid allows this by specifying :production and :development environments.

Using MongoDB

So far in ruby we have met several different types of object e.g. String, FixNum, Array and Hash. To interact with the database we will define our own type of object using a class:

class User
    include Mongoid::Document

    field :name
    field :email
end

This class defines an object that will be saved to the database. A User will have two properties: name and email set up using the field command. The line include Mongoid::Document is the bit that tells ruby how to save the object.

Task:
  1. Open mongo1/db_examples.rb in Sublime text.
  2. With a partner, work through the examples in the file, copying and pasting into irb.

Creating a new user

# create a new user object
u = User.new(:name => "Tom", :email => "tom@example.com")

# get the properties
u.name #=> "Tom"
u.email #=> "tom@example.com"

# change the name
u.name = "Tom Close"

# save to the database
u.save #=> true

Getting users from the database

# count the number of users
User.count

# find the first user
User.first

# find the user with name Tom Close
User.find_by(:name => "Tom Close")

# pull all users out of the database ...
users = User.all
#=> #<Mongoid::Criteria
#  selector: {}
#  options:  {}
#  class:    User
#  embedded: false>

# ... and print their names
users.each {|u| puts u.name}

Mongo with sinatra

require 'sinatra'
require 'mongoid'
require 'json'

## Mongoid setup
## =============

Mongoid.load!("mongoid.yml", :development)

class Fruit
  include Mongoid::Document

  field :name
end
get '/' do
  @fruits = Fruit.all
  erb :index
end
<ul>
  <% @fruits.each do |f| %>
    <li><%= f.name %></li>
  <% end %>
</ul>
<h3>Add a new fruit</h3>

<form method='post'>
  <label>Name of fruit</label>
  <input type='text' name='fruit_name'>
</form>
post '/' do
  name = params[:fruit_name]
  f = Fruit.new(:name => name)
  f.save
  @fruites = Fruit.all
  erb :index
end
Task:
  1. Have a look at the example_app in mongo1.
  2. Have a look in the (mostly empty) mongo1/app.rb.
  3. Have a look at the finished app.
  4. Try and make your app work like that.