-
Notifications
You must be signed in to change notification settings - Fork 190
Tutorial
This is a detailed Rails tutorial showing how to create a Rails application for a startup prelaunch signup site.
This app extends the rails3-devise-rspec-cucumber example app. You can see a tutorial for the rails3-devise-rspec-cucumber example app. Devise gives you ready-made authentication and user management.
See a list of additional Rails examples, tutorials, and starter apps.
Follow the project on Twitter: @rails_apps. Tweet some praise if you like what you’ve found.
This tutorial documents each step that you must follow to create this application. Every step is documented concisely, so a complete beginner can create this application without any additional knowledge. However, no explanation is offered for any of the steps, so if you are a beginner, you’re advised to look for an introduction to Rails elsewhere. See a list of recommended resources for Rails.
If you follow this tutorial closely, you’ll have a working application that closely matches the example app in this GitHub repository. The example app is your reference implementation. If you find problems with the app you build from this tutorial, download the example app (in Git speak, clone it) and use a file compare tool to identify differences that may be causing errors. On a Mac, good file compare tools are FileMerge, DiffMerge, Kaleidoscope, or Ian Baird’s Changes.
If you clone and install the example app and find problems or wish to suggest improvements, please create a GitHub issue.
To improve this tutorial, please edit this wiki page.
Cut and paste the code.
To create the application, you can cut and paste the code from the tutorial into your own files. It’s a bit tedious and error-prone but you’ll have a good opportunity to examine the code closely.
Use the ready-made application template to generate the code.
You can use an application template to generate a new Rails app with code that closely matches the tutorial. You’ll find an application template for this tutorial in the Rails Application Templates repository.
Use the command:
$ rails new myapp -m https://github.com/RailsApps/rails3-application-templates/raw/master/rails-prelaunch-signup-template.rb -T
Use the -T flag to skip Test::Unit files.
This creates a new Rails app (with the name myapp) on your computer. It includes everything in the example app. You can read through the tutorial with the code already on your computer.
Use the rails_apps_composer gem to create a reusuable application template.
This is optimal if you are creating a “starter app” based on this example app but wish to customize the code for your own preferences.
Each step in this tutorial has a corresponding application template recipe from the Rails Apps Composer recipes repository. You can create your own application template using the template recipes. To do so, download the Rails Apps Composer project, customize recipes as needed, and follow the instructions to create a reusable application template file.
Before beginning this tutorial, you need to install
- The Ruby language (version 1.9.3)
- Rails 3.2
Check that appropriate versions of Ruby and Rails are installed in your development environment:
$ ruby -v
$ rails -v
See Installing Rails 3.2 and Managing Rails Versions and Gems for detailed instructions and advice.
You’ll start by generating the rails3-devise-rspec-cucumber example app using an application template.
Use the command:
$ rails new rails-prelaunch-signup -m https://raw.github.com/RailsApps/rails3-application-templates/master/rails3-devise-rspec-cucumber-template.rb -T
Use the -T flags to skip Test::Unit files.
This creates a new Rails app (named rails-prelaunch-signup) on your computer. For this tutorial, the name is “rails-prelaunch-signup.” You can use a different name if you wish.
The application generator template will ask you for your preferences. For this tutorial, choose the following preferences:
Would you like to use Haml instead of ERB? Yes.
Would you like to use RSpec instead of TestUnit? Yes.
Would you like to use factory_girl for test fixtures with RSpec? Yes.
Would you like to use machinist for test fixtures with RSpec? No.
Would you like to use Cucumber for your BDD? Yes.
Would you like to use Guard to automate your workflow? No.
Would you like to enable the LiveReload guard? No.
Would you like to use Devise for authentication? Yes.
Which front-end framework would you like for HTML5 and CSS3? Twitter Bootstrap
Would you like to use ‘rails-footnotes’ during development? No.
Would you like to set a robots.txt file to ban spiders? No.
After you create the application, switch to its folder to continue work directly in the application:
$ cd rails-prelaunch-signup
If you’re open sourcing the app on GitHub, please edit the README file to add a description of the app and your contact info. Changing the README is important if you’re using a clone of the example app. I’ve been mistaken (and contacted) as the author of apps that are copied from my example.
If you’re creating an app for deployment into production, you’ll want to set up a source control repository at this point. If you are building a throw-away app for your own education, you may skip this step.
See instructions for Using Git with Rails.
The application uses the following gems:
The rails3-devise-rspec-cucumber application template sets up your gemfile.
See an example Rails 3.2 Gemfile.
See Installing Rails 3.2 for advice and details. It’s a good idea to create a new gemset using rvm, the Ruby Version Manager.
Install the required gems on your computer:
$ bundle install
You can check which gems are installed on your computer with:
$ gem list --local
Keep in mind that you have installed these gems locally. When you deploy the app to another server, the same gems (and versions) must be available.
In this example, we’ll use Haml instead of the default “ERB” Rails template engine. The rails3-devise-rspec-cucumber example app sets up Haml. You can see details about adding Haml to Rails.
The rails3-devise-rspec-cucumber example app uses RSpec for unit testing. Run rake -T to check that rake tasks for RSpec are available. You should be able to run rake spec to run all specs provided with the example app.
The rails3-devise-rspec-cucumber example app set up Cucumber for specifications and acceptance testing. You should be able to run rake cucumber (or more simply, cucumber) to run the Cucumber scenarios and steps provided with the example app.
Set up the database and add the default user by running the commands:
$ rake db:migrate $ rake db:seed
Set up the database for testing:
$ rake db:test:clone
You can check that the example app runs properly by entering the command
$ rails server
To see your application in action, open a browser window and navigate to http://localhost:3000/. You should see the default user listed on the home page. When you click on the user’s name, you should be required to log in before seeing the user’s detail page.
Stop the server with Control-C.
Arguably, for a simple application like this, you don’t need a lot of ceremony. There’s no need for a written specification. And no need for tests, right? Just code it up. However, for the purposes of this tutorial, I want to show the practices that establish a good software development process. This is just your prelaunch app but you may want to explore a process that can guide development of a more complex application you may build later. To that end, we’ll begin by writing user stories. We’ll write a short specification for our feature set using Cucumber scenarios. Then we’ll create acceptance tests using Cucumber step definitions. We’ll code and test each feature after we have created acceptance tests. By thinking about the process that leads from concept to code, you’ll be better prepared to begin building a more complex application for a real business.
User stories are a way to discuss and describe the requirements for a software application. By making a list of user stories, you’ll force yourself to describe what your application will do. The process of writing user stories will help you identify all the features that are needed for your application to be useful. Finally, breaking down the application’s functionality into discrete user stories will help you organize your work and track progress toward completion.
User stories are generally expressed in the following format:
As a <role>, I want <goal> so that <benefit>
As an example, here are three user stories we will implement for this application:
*Request Invitation* As a visitor to the website I want to request an invitation so I'll be notified when the site is launched *See Invitation Requests* As the owner of the site I want to view a list of visitors who have requested invitations so I can know if my offer is gaining traction *Collect Email Addresses* As the owner of the site I want to collect email addresses for a mailing list so I can send an announcement when I launch the site
You can see a list of user stories that have been implemented. There is also a list of user stories that have not been implemented. If you have ideas for additional features for this application, edit the file and submit a pull request. Or simply create a GitHub issue.
The next step in our development process is to pick a user story and turn it into a specification that can guide a software developer in implementing a feature. If you are the software developer who implements the feature you may not need a specification. Your user story is all you need to guide you to code the implementation. But if you are part of a team of developers or a manager who gives others the task of implementing a feature, you will need a specification to communicate what needs to be accomplished. User stories can guide development but you may want to use techniques of behavior-driven development to turn user stories into exact specifications that can be used as the basis for acceptance testing (automated tests that show if developers have succeeded in implementing a specification) or integration testing (automated tests that assure you that your application runs as intended). So that we’ll have integration tests for this application, we’ll write a Cucumber scenario for our first user story.
The features directory contains our Cucumber feature files. We can organize Cucumber feature files any way we wish by placing them in subdirectories. For this application, we’ll organize features by roles in subdirectories for “visitors” and “owner”. Create a subdirectory features/visitors and then create the following file:
features/visitors/request_invitation.feature
Feature: Request Invitation
As a visitor to the website
I want to request an invitation
so I can be notified when the site is launched
Background:
Given I am not logged in
Scenario: User signs up with valid data
When I sign up with valid user data
Then I should see a successful sign up message
Scenario: User signs up with invalid email
When I sign up with an invalid email
Then I should see an invalid email message
This Cucumber feature file contains the specification needed to implement the user story “Request Invitation.”
Cucumber scenarios can be read as plain English text. Alone, they serve as specifications. To create an acceptance test or integration test, we must write test code for each step in a scenario, called “step definitions.”
Thanks to the power to open source, we don’t need to write all the step definitions for this feature. The rails3-devise-rspec-cucumber example app provides step definitions for a “Sign up” feature that has a nearly identical specification. Look at the file features/step_definitions/user_steps.rb and you’ll see the following step definitions:
Given /^I am not logged in$/ do visit '/users/sign_out' end . . . When /^I sign up with valid user data$/ do sign_up valid_user end . . . When /^I sign up with an invalid email$/ do user = valid_user.merge(:email => "notanemail") sign_up user end . . . Then /^I should see a successful sign up message$/ do page.should have_content "Welcome! You have signed up successfully." end . . . Then /^I should see an invalid email message$/ do page.should have_content "Email is invalid" end
We can run our integration test with the following command:
$ bundle exec cucumber features/visitors/request_invitation.feature --require features
Be sure you’ve set up the database for testing before running Cucumber:
$ rake db:test:clone

Tutorial