rvm install 2.1.1 rvm --default use 2.1.1 gem install rails --version=4.1.0 rails new who_wants_rails cd who_wants_rails rake db:create
Now, the aim of this series of tutorials is to implement a popular quiz format with Ruby on Rails, learning about the components of the framework as we go. Let's start with a model, as I said in Part 1, models handle interaction with the underlying database and house the logic of your application, defining things it can do.
A model is a type of class, which can broadly be defined as a type of thing. You can create an instance of that class, which is one of that type of thing. A class defines methods which are actions which can be done to instances and class methods which can be done. Also an instance of a class can have attributes, which are specific pieces of information about that thing.
I realise that's a little vague, but it's a brief introduction to the terminology I'm using.
Lets put some of this into practise:
Now, the word 'model' is not an accidental term, in software, we use classes to represent (or 'model') other things. As a general principal, if we can define what something is, what we know about it, and what it does in logical terms, we can model it with software. So lets define what we know about a question in our popular quiz format.
- It has some text, the question itself, which people want to see before answering it
- It has 4 possible answers
- One answer is correct
- It is used at one of 15 points in the quiz format
- Users may answer the question, and uncover whether or not they have answered correctly.
Lets start with the simplest of these, the Level model. Rails provides a command which will create a model, along with the other files we need for it to work. We need to define what attributes an instance of the Level class will have. It'll have a name (for instance, "£100") and a level number (which will define it's order in the format). So, lets try using `rails g` (short for generate) to create this:
rails g model Level name:string level:integer
This tells us not only the attributes of a level, but what type of data each one will contain, it says that the name will be a string, which is computer-speak for some text and that level will be an integer, which is maths-speak for a whole number.
The result will look a little something like this:
Models in Ruby on Rails are a class which handles what is called object-relational mapping, maps a table of data in the database to the class, and each row in that table to an instance of the model. This means that there has to be a table in the database, to store attributes for instances of the model. The fisrt file mentioned in the output of the `rails g` action, above, is a migration. This is a rails definition of a change in the database. The content of the migration looks like this...
We can run any migrations which haven't yet been run with this command:
This will add the 'levels' table to the database we created at the start of this tutorial. It looks like this:
More importantly, it creates the model itself, stored in the file at app/models/level.rb, currently, it's got almost nothing in it:
What it does do, is define a class called Level, the next part, ActiveRecord::Base is the part of Ruby on Rails which handles the above-mentioned ojbect-relational mapping. Since this is our first model, lets try it out with the rails console, which we can open with
or, more concisely:
Once this is opened, we can use our application directly using lines of Ruby code. We'll start by making a new instance of Level (with `Level.new`) and assigning it to a variable named `level`.
You'll notice that we have a run-down of the attributes of our new level, they are all, so far, nil (which means nothing). But you may also notice that it has an id (which is a primary key, used to uniquely identify a specific level), and created_at and updated_at columns. The last two are defaults of Rails models, created_at is set when you first save, and updated_at is set whenever you save it.
First things first, however, lets feed the attributes we want to Level.new, to make a level with the attributes we want:
Oops, I've accidentally named it $100, but I meant it to be £100. I'll use the instance of Level, but change it's name attribute to £100...
You'll notice that `level.name` means the name attribute of that object, and that `level.name = ` defines that attribute. But when we close the terminal, this instance of the Level class will be lost, unless, of course, we save it to the database:
So, level.save ran an SQL statement (it shows this for people who are familiar with SQL, the standard language for interacting with databases, but you don't need to worry about it for now), and then returned 'true' meaning it's saved.
Now when we look at the level object, we see that it's had an id assigned, as well as the time it was created and updated.
As I mentioned above, id is used to find this specific level again, even if we close the console and open it again. So lets try that:
So we've used a class method, find, to find an instance of Level, and we've passed it an argument (which is a specific piece of information telling a method how to do what it does) with the id of the level we want.
Lets try this with a few new levels:
Here I've used Level.create to both make a new instance of Level and save it to the database in one action, with it I've created 4 new instance of Level, in the database.
But I won't always know the id of everything instance of all my models, so how do I find them again? Here are some useful methods to call on your models...
- Level.find - find a n instance of Level by it's id
- Level.first - returns the first instance found in the database
- Level.all - returns all of the instances of that model
- Level.where - You can pass this conditions to find one or more Levels
That's found it (although that's actually a collection of objects, with one in it, to get the object itself you should use
Level.where(:level => 2).first
Hopefully this has been a useful starter in how to use Models in Ruby on Rails, there's still a lot to learn here, validations to make sure the data saved to your database is suitable, relationships between instances of different models, more advanced querying, and writing your application logic as methods for instances of a class. But all that is other blog posts, for other days.
Yes, we haven't got very far, but Rails is big, and to understand it, you need to take baby steps. Suffice to say we will eventually be able to produce a quiz with this.
For now, I hope this is helpful. As ever feel free to contact me (@MarmiteJunction) and ask about anything that doesn't make sense to you. I may not be explaining all of this very well.