CS142: Web Programming and Security

Project 8: Forms and Sessions

Due: Wednesday, March 4, 2009
15 points

In this project you will use Ruby on Rails to create forms that allow users to add photos and comments to the photo-sharing Web site from Project 6. You will also add a simple login mechanism.

Step 1: Project Setup

As with Project 6, we have created a skeleton for this project that provides the beginnings of a Rails application and sets up a database and an initial collection of photos for your application to use. The skeleton is a zip file available at p8skeleton.zip. Unzip the skeleton file to create a new application in a directory named project8. For Windows this directory should be a child of the rails_apps directory in your InstantRails installation; on the Macintosh it should be a child of your home directory. Next, invoke the following shell commands to finish setting up the skeleton project (refer back to Project 6 for platform-specific instructions on how to start a shell):

cd project8
rake db:create
rake db:migrate
mysql -u root project8_development < db/project8.sql

These commands will create a database for the project and fill in some initial data for your project to use.

Start up the new project with a Mongrel server in the same way as for Project 6, and make sure that everything is installed correctly by visiting the URL http://localhost:3000/test/main in your browser. You should see a page saying "Congratulations: you have installed the skeleton for Project 8".

Copy over your controller and view files from project6 to project8 and make sure that you can view users and photos as before. If you do not have working code for Project 6 you may contact the TAs and they will provide you with controllers and views to start from. However, you're better off starting from your own code if possible, since you already understand it.

Step 2: Login

For this project you must add support for three forms. Each form uses 2 URLs, one to display the form and one to receive POST requests for the form. The first form will be used to log in, so that your application knows which user is providing new photos and comments. For this project users will log in using their last name, but with no password protection: anyone can log in as any user (obviously this would not provide acceptable security for a real application). The URL /login/form should display a login page with a form containing a text entry for the user's last name. When the form is submitted, it should post its data to /login/post. Once the post has been processed, your application should redirect the browser to /pics/user/id to display that user's photos. If the user enters an incorrect login name then you must redisplay the login form with an error message about the problem.

You will need to create a new controller that implements the login URLs. To do that you can invoke the shell command

ruby script/generate controller login form

Note that you only need one view for this controller: the /login/post URL redirects without generating any HTML.

Step 3: New Comments

Once you have implemented user login, the next step is to implement a form for adding comments to existing photos. Implement a URL /pics/commentForm/id that displays a form where a user can add a comment for the photo whose primary key is id. You should also display the photo on this page so the user can see it while he/she is typing the comment. The form should post to the URL /pics/commentPost/id; your implementation for this URL should create a new comment in the database using the Rails models. The comment must include the identifier of the logged in user and the time when the comment was created. Make sure that new comments can be viewed in the same way as the pre-existing comments.

Once you've implemented the form for new comments, modify the page /pics/user/id to display a "New Comment" link next to each photo, which will go to the new-comment form for that photo.

Your implementation must handle the following errors:

  • If there is no user logged in that it should not be possible to add comments.
  • Do not allow empty comments: return to the new-comment form and display an error message

Step 4: Photo Uploading

The final piece of this project is to allow users to add new photos. To do this, implement a URL /pics/photoForm, which displays a form allowing the user to select a photo file for upload. The form should post to the URL /pics/photoPost, which copies the incoming photo data to a file in the directory project8/public/images and creates a new record in the database containing the name of the photo file, the creation time, and the identifier of the user. Also, add a "New Photo" link at an appropriate place in one of your existing pages, which users can click to go to the photo upload form.

Your implementation should check to make sure that a user is logged in and prevent photo uploading if not.

Additional Requirements, Hints, etc.

  • You must work alone for this project. You may discuss general approaches with other people, and you may ask for help if you get stuck, but you must design your own Web pages and type your own code.
  • Your application must generate valid XHTML. You can use http://validator.w3.org to validate your XHTML.
  • As with Project 6, you don't need to spend a lot of time on the appearance of your pages, but they must be neat and understandable. Your forms must contain enough labels and other text so that an average Stanford student can understand how to use them.
  • The database for this project has the same schema as for Project 6. See the Project 6 writeup for details.
  • In Rails the method session returns a hash you can use to store and retrieve session data: Rails saves this hash automatically and makes it available in future requests for the same session.
  • In order to upload files in a Rails form, do the following things:
    • In the form_for method call, supply an argument :html => { :multipart => true } as shown on page 502 of "Agile Web Development with Rails".
    • Use form.file_field to generate the form element (also shown on page 502 of the book).
    • When the form is posted, you can reference the uploaded file with the params hash: if the first argument to form_for was :xyz and the first argument to form.file_field was :abc, then the uploaded file will be available as params[:xyz][:abc]. This is an object of class ActionController::UploadedFile, which supports IO methods such as read. The object also provides a method original_filename, which returns the name of the file that was selected by the user in their browser.
    • Do not store uploaded photos in the database as shown in the book; store them on disk in the directory project8/public/images.
  • The easiest way to add a new action method to an existing controller is to edit the controller file to add a method, then create a new view for that action in the app/views subdirectory corresponding to the controller.
  • The Ruby method DateTime.now returns a string containing the current date and time in the right format for storing in the database.
  • If bugs in your software cause your database to get corrupted, or if you'd just like to clear out the new comments and photos you have added, you can reset your database with the following steps:
    • Invoke the following shell command:
      mysql -u root -e "drop database project8_development;"
      This will delete the database for the project.
    • Go to the directory project8/public/images and delete all of the new image files you have created, leaving only the original ones.
    • Re-invoke the commands in Step 1 to reinitialize the database.

Extra Fun (but no extra credit)

If you are having so much fun with this project that you just don't want to stop, here are some additional things you can do:

  • Make the login mechanism more convenient for users. If a user attempts to perform an operation that requires login, such as uploading a photo or creating a new comment, redirect to the login page but remember what the user was trying to do. Once the user has successfully logged in, automatically redirect back to the activity that was interrupted.
  • Learn about Rails layouts, and use a layout to display a banner at the top of every page displaying a name for your application and the name of the logged-in user, along with a link the user can click to log out. Use the URL /login/logout to implement the log-out functionality. If no user is logged in, then instead of the username and logout link your layout should display a "Login" link, which will go to the login page.


Use the standard class submission mechanism to submit your entire project8 directory and its descendents. Please indicate in a README file whether you developed on Windows or a Macintosh (we may need this information in order to test your solution). Note: If you have added more than a couple of new images, please clean up your data before submitting, as described above. Be sure to test your project one more time after resetting the database, just to make sure everything is still OK.

Section Material

Here are the section notes.