-
Notifications
You must be signed in to change notification settings - Fork 0
Web UI
Deadline: October, 3, 2012, 12:00
You are asked to implement a simple graphical web-based user-interface (view) using the User
and Item
model you implemented in the last week’s homework.
It is mandatory to use the sinatra framework, that is "a Domain-Specific Language (DSL) for quickly creating web applications in Ruby with minimal effort".
HTTP defines several methods (also called verbs) to perfom actions on URLs. The main ones are GET
and POST
respectively to fetch and send data to URL.
Sinatra maps verbs and URL with ruby code via routes:
get '/' do
"<h1>Hello World</h1>"
end
Usually, the ruby code does not produce HTML as above, but instead forwards to a view (also called template):
get '/' do
haml :hello_world
end
The above code will renders the file hello_world.haml
, that simply contains text Hello World
.
To pass values to a template for rendering, use the options hash idiom:
get '/' do
haml :print_time, :locals => { :time => Time.now }
end
The above code passes the current time into a paramter time
that can be used in the template print_time.haml
and formatted accordingly, e.g.
Time: #{time.strftime("%H:%M:%S")}
Sinatra provides the "C" in the MVC pattern: the routes are the controller(s). The template engine is the "V" in MVC. The controller manipulates the model, while the view simply renders it.
You should try to postpone rendering issues (like formatting dates) as late as possible to keep the separation between controllers and views.
You can go through Sinatra's README for more examples of routes, parameter passing, and template engines.
You can use the template engine of your choice, but we recommender either haml or erb.
We ask you to structure your project as follows
/trade
/app
app.rb
/public
static-file
/models
/module
class-in-module.rb
/views
/controllers
main.rb
authentication.rb
/test
Pay attention to name the main file app.rb
.
You might want to serve certain static files like images, CSS, etc. To do so, you can use
set :public_folder, 'app/public'
in the app
file to exclude a folder from matching other routes. Files in this folder will be served directly.
Persistency using database is outside the scope of the ESE lecture, so we simply ask to keep the model in memory in a way similar to the exercise from last week.
You can load test data on startup using a configure
block in the app
file:
configure :development do
University::Student.named( 'John' ).save
...
end
See Configuration in Sinatra's doc.
Method save
add the student to a class variable students
:
class Student
# class variable
@@students = []
...
def self.all
@@students
end
def self.by_name name
@@students.detect {|student| student.name == name }
end
# add the instance to the list of students
def save
@@students << self # or @@students.push(self)
end
...
Sinatra is a very simple framework. It does not by iteself support authentication.
We sketch now how you can easily add support for authentication using Sinatra's sessions.
- First, you need to enable sessions in the main application file
enable :sessions
- Add a login page that will check the username and password; if the login succeeds it sets the parameter
name
in the session, e.g.
session[:name] = username
- Add a logout page that resets the parameter in the session to
nil
, e.g.
session[:name] = nil
- For the other pages, check the value of
session[:name]
. If it isnil
, redirect to the login page, e.g.
redirect '/login' unless session[:name]
The Post/Redirect/Get pattern (also called Get after Post) is a web development pattern that prevents some duplicate form submissions, and make sure the browser's back button works in a predictable way.
get "/"
haml :list_students, :locals =>
{ :students => University::Student.all }
end
post "/add"
... extract parameters from request ...
student = ... create student ...
student.save
redirect '/'
end
With this pattern, GET
methods should be idempotent; they should not update the model. Only POST
methods should update the model.
It is not mandatory to enforce this pattern, but we encourage you to do it.
#Study the Code
Nothing is better than code, no?
For the impatient, you can jump to the code of ese2012-sinatra-basics, a simple web UI for the University::Student
model of last week.
For a smoother introduction and a more comprehensive example, you can read the following blog serie of yours faithful zombiecalypse: installation, basics, using a model, REST, and sessions. This tutorial covers additional useful topics:
- HTML forms
- Helper methods between the view and the controller
- Dealing with relative paths between files
- Authentication with password hash
- Identity and equality of entities with identifiers
- RESTful web applications
It is not mandatory to go through it to implement the requirments below, though.
The web application must support the following requirements.
-
User authentication -- If the user is not authenticated, he/she is redirect to the login page. Authentication suceeds if the password = the username.
-
Show all active items -- The default page lists all active items in the system. For each item there is
- the name
- the price
- a link to the owner
- a link or button to buy the item
-
List items of a user -- The page lists all items owned by the user and indicates whether they are active (to sell) or inactive (not to sell).
-
Buy an item -- From the default page, a user can buy an item. If the transaction suceeds, the page is updated to show the new state of the system; otherwise an exception is raised.
-
Test data -- Please prepare test data that are loaded on startup. The must be a user
ese
that we can use to log in the system and test the other features.
Answer the following questions in a file answers.txt
that you will deliver with the sources:
- Explain how a typical HTTP request is processed with the framework (the request lifecycle)
- Why should GET requests be indempotent?
- Where should you format data for rendering?
As in the last excercise you have to use the github infrastructure to provide your solutions for this exercise. There is a lot of documentation available on the net about git, check out the links we provide in the resources section.
We ask you to create a repository ese2011-web-ui
where you will commit your sources on the master branch. Everybody has by default read-only access to the repository. However in a way for us to commit remarks in your repository, add us as collaborator (ewernli, jokr, zombiecalypse
).
As the final deliverable of these exercises we expect one of the author to publish the solutions to the repository {git account}/ese2012-web-ui
by Wednesday, 3. October 2012, 12:00. Make sure that you include all code of Task 2 and that it runs correctly if we use
cd ese2012-web-ui
ruby app/app.rb
Include the answers to Task 3 in a file called answers.txt
. Then send a mail to [email protected]
with the following subject line: "Exercise 2: Web UI", give the names of the authors, and the git repository to pull the code from.