Want a free year on Tuts+ (worth $180)? Start an InMotion Hosting plan for $3.49/mo.
Welcome to part I of the tutorial series on creating a quiz or survey app with jQuery Mobile and Rails. This series will demonstrate how to build a mobile compatible web application that will allow users to answer a series of questions in a wizard like fashion.
jQuery Mobile contains several useful, out-of-box features for making our web application usable on a variety mobile devices. In most cases, the basic template and CSS themes that come with jQuery Mobile will be sufficient. However, since all of the templating is done in CSS, we can customize the look and feel of our site pretty easily.
jQueryMobile is an ideal framework choice when building a mobile web application for many reasons, including:
1) Since the framework is built upon jQuery, there is a small learning curve for anyone who has used jQuery on the web.
2) It's currently compatible with many major platforms including: iOS, Android, Blackberry, Palm WebOS, Nokia/Symbian, Windows Mobile, etc.
3) The compressed size of the included libraries is approximately 12k which is very lightweight for the capabilities offered.
For the backend, we will be using Rails 3 with a few gems, including Typus.
To start, lets create a new rails app:
rails new .
Make sure you have the latest version of the rails gem installed. If you have any apps you are developing that require Rails 2, I suggest you research and install RVM (Ruby Version Manager). This will save you many headaches that can be caused by gem versioning issues.
Next, lets add our gems to our Gemfile:
source 'http://rubygems.org' gem 'rails', '3.0.7' gem 'sqlite3-ruby', :require => 'sqlite3' gem 'jquery-rails' # Admin gem 'typus', :git => 'http://github.com/fesplugas/typus.git' gem 'acts_as_list'
As you can see, we will be using Rails 3.0.7 as it is the latest stable version of Rails as of this writing. We'll also be overriding the default Prototype JS libraries that come with Rails by installing the jquery-rails gem. Since jQueryMobile will obviously require the jQuery base library, then we really don't have any reason to keep the included Prototype libraries around.
For our admin section, we will install the Typus gem and acts_as_list. With just a small amount of configuration, Typus will provide an entire backend for managing the questions we will create for our survey. Acts as list works seamlessly with Typus and will allow us to easily control the order of our questions.
Now we can run the bundler to install our gems:
Both the jQuery gem and the Typus gem have generators that work to essentially have the gems install themselves. This is accomplished by running the following commands while in the app directory:
rails generate jquery:install rails generate typus
By default, Typus comes without any sort of authentication gate. Since this is almost like direct access to the database, we should secure it as a first step. The simplest method of securing it will be to add basic http auth. This is obviously not hyper secure, but for the purposes of our tutorial it will suffice. In order to do this, we need to add the following lines to the config/initializers/typus.rb file:
config.admin_title = "survey" config.authentication = :http_basic config.username = "admin" config.password = "pass"
This will prompt the user to enter a username and password when the /admin URL is accessed.
Now that our app is fully setup, we can start generating our resources and database schema. We can use the Rails shorthand method of doing this right from the command line with the following:
rails generate resource question question:string position:integer rails generate resource choice choice:string question_id:integer rails generate resource answer question_id:integer choice_id:integer rake db:migrate
We now have 3 tables in our database. One will house the questions we are going to ask the user. Each question will have many choices, and an answer will be a record storing the combination of I.D.s for a question and a choice. Since choices will only have one question, the question_id field in the answers table is not really necessary. We are going to put it here as an easy accessor for simplifying queries such as pulling the number of answers for a question. The position field in the questions table will allow us to specify the order of questions as they will appear in our survey.
To add these relationships to our models, we will modify them as follows:
class Question < ActiveRecord::Base acts_as_list has_many :choices end
As you can see above, we are adding the acts_as_list plugin to this model so that we can alter the order of appearance for each question in our survey.
class Choice < ActiveRecord::Base belongs_to :question end
class Answer < ActiveRecord::Base belongs_to :question belongs_to :choice end
Done! Now that our resources and database tables have been generated, we need to create some controllers namespaced under an admin folder for Typus. To do this we run the following commands:
rails generate controller admin/answers rails generate controller admin/choices rails generate controller admin/questions
Next, we need to change the first lines in each of our controller files to make the controller inherit from ResourcesController instead of our base ApplicationController. In Typus, once we inherit from ResourcesController, we get some powerful CRUD functionality out of the box without having to write any further code. Below are the necessary replacements:
class Admin::AnswersController < ApplicationController
class Admin::AnswersController < Admin::ResourcesController
class Admin::ChoicesController < ApplicationController
class Admin::ChoicesController < Admin::ResourcesController
class Admin::QuestionsController < ApplicationController
class Admin::QuestionsController < Admin::ResourcesController
Almost there! Now we need to add some configuration statements to our Typus configuration file. If there are any other yaml files located in the config/typus directory, we can delete them because they are not necessary. Typus likely created sample configuration files when we ran our generator statement. Let's create a file called typus.yml located here: config/typus
First, we'll add the configuration statements for the Choice model:
Choice: fields: default: choice, question_id, question form: choice, question_id, question order_by: relationships: question filters: created_at, question search: application: survey Question: fields: default: question, position form: question order_by: position relationships: choices filters: created_at search: question application: survey
Let's break this down:
Choice: fields: default: choice, question_id, question form: choice, question_id, question
In just a few lines of configuration, Typus will create a great deal of backend functionality for us. To start, we will specify the fields that we are allowed to edit. The default section of the fields definition will allow us to set which fields will be displayed in our list. In this case, it is the same set of fields that we will allow our admin to set in our create and update forms. This is specified in the form section of the fields definition.
By default our choices will be ordered in the order they are created, so we don't need to specify anything for order_by.
Each choice belongs to one question, so we can define a relationship of question to our choice model. Typus will automagically design our forms to account for how data records relate to one another.
filters: created_at, question
Filters can be defined in typus simply by listing fields and/or relationships in the filters definition. Based on the field type, typus will create filter functionality in the backend. In the case of created_at, this will be a set of drop downs to specify a date. For question, this will be a drop down of all the questions stored in the database.
search: application: survey
The search definition is of no use to us for this model as we will unlikely be searching for any choices. Had we specified fields here though, typus would provide us a search box so we could filter the records stored in our DB by a search term. The application definition here is the name of the application our models are under which we are calling "survey."
As a final clean up step let's remove the file public/index.html which is going to block our default route.
Now we can start our server:
Visit the following URL in your browser to test out our newly created admin:
Next Time. . .
This concludes part I of our tutorial series on creating quiz or survey app in Rails and jQueryMobile. Stay tuned for part II where we will implement our jQueryMobile frontend.