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 toform_for
was:xyz
and the first argument toform.file_field
was:abc
, then the uploaded file will be available asparams[:xyz][:abc]
. This is an object of class ActionController::UploadedFile, which supports IO methods such asread
. The object also provides a methodoriginal_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
.
- In the
- 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.
- Invoke the following shell command:
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.
Deliverables
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.