1
Dr Alexiei Dingli
Web Science Stream
Web 2.0
2
• We’ll implement a voting mechanism
• Using AJAX
Web 2.0
3
• ruby script/generate model Vote story_id:integer
Creating the vote model
4
class CreateVotes < ActiveRecord::Migration
def self.up
create_table :votes do |t|
t.integer :story_id
t.timestamps
end
end
def self.down
drop_table :votes
end
end
The vote migration
5
• rake db:migrate
Apply the migration
6
• In the case of votes– A story might have many votes– Has_many is the relationship to use
• App/models/story.rb– has_many :votes
More on relationships
7
• ruby script/console
s = Story.find(:first)
s.votes
s.votes.create
s.votes.size
Let’s test it ...
8
• App/models/vote.rb• Add
– belongs_to :story
• Use the reload! command in the console– Try
• v = Vote.find(:first)• v.story
Finalising the relationship
9
Stories_controller.rb
def index
@story = Story.find(:first, :order => 'RANDOM()')
end
def new
@story = Story.new
end
def show
@story = Story.find(params[:id])
end
Showing our stories
10
• App/views/stories/show.html.erb
<h2><%= @story.name %></h2>
<p><%= link_to @story.link, @story.link %></p>
Displaying the stories!
11
• Start a server– ruby script/server
• Goto– http://127.0.0.1:3000/stories/1
Let’s see what we have so far ...
12
• Change the index.html to
A random link:
<%= link_to @story.name, story_path(@story) %>
Better randomization
13
• Generate– ruby script/generate controller Votes create
• Arrange the routes– Routes.rb
• map.resources :stories, :has_many => :votes
• Create the routes– rake routes
Let’s create the votes
14
Nested routes of the form ...
/stories/:story_id/votes
/stories/1/votes
Looking at the rake routes
15
• Asynchronous JavaScript and XML– Make web browser communicate with a server without
reloading the page– Also called remote scripting– More dynamic and responsive experience just like in a
desktop application– Uses
• XMLHttpRequest, XHTML, CSS and DOM– Supported by most browsers– Used in Web 2.0 applications (Digg, Flickr, etc)
Ajax
16
• Rails – ships with Ajax support– encourages its use– is bundled with the Prototype JavaScript
library• http://www.prototypejs.org/
– And also script.aculo.us which takes care of visual elements• http://script.aculo.us/
Rails + Ajax
17
Core Effects:
Effect.Highlight, Effect.Morph, Effect.Move, Effect.Opacity, Effect.Scale, Effect.Parallel, Effect Queues
Combination Effects:
Effect.Appear, Effect.BlindDown, Effect.BlindUp, Effect.DropOut, Effect.Fade, Effect.Fold,Effect.Grow,
Effect.Puff, Effect.Pulsate, Effect.Shake, Effect.Shrink, Effect.SlideDown, Effect.SlideUp,
Effect.Squish, Effect.SwitchOff, Effect.ScrollTo
Effect helpers:
Effect.Transitions, Effect.Methods, Effect.tagifyText, Effect.multiple, Effect.toggle
Behaviours:
Draggable, Droppables, Sortable, Form.Element.DelayedObserver
Controls:
Ajax.InPlaceEditor, Ajax.InPlaceCollectionEditor, Ajax.Autocompleter, Autocompleter.Local, Slider
Miscellaneous:
Builder, Sound, Unit Testing
Some features of script.aculo.us
18
• Just underneath the <title> tag of application.html.erb add– <%= javascript_include_tag :defaults %>
• This will automatically include– Prototype.js– Effects.js– Dragdrop.js– Controls.js– Application.js
Adding the JavaScript libraries
19
<h2>
<span id="vote_score">
Score: <%= @story.votes.size %>
</span>
<%= @story.name %>
</h2>
<p>
<%= link_to @story.link, @story.link %>
</p>
<div id="vote_form">
<% form_remote_tag :url => story_votes_path(@story) do %>
<%= submit_tag 'shove it' %>
<% end %>
</div>
Modifying the stories/show.html.erb
20
#vote_score {
float: right;
color: #9c9;
}
#vote_form {
margin: 10px 0;
}
#vote_form input {
padding: 3px 5px;
border: 3px solid #393;
background-color: #cfc;
text-decoration: none;
color: #393;
}
#vote_form input:hover {
background-color: #aea;
}
Adding some styles
21
• Start a server– ruby script/server
• Goto– http://127.0.0.1:3000/stories/1
Let’s see what we have so far ...
22
class VotesController < ApplicationController
def create
@story = Story.find(params[:story_id])
@story.votes.create
end
end
Adding votes
23
• Used to modify parts of an existing page• Send JavaScript commands• Make a view called create.rjs and add the
following:– page.replace_html 'vote_score', "Score:
#{@story.votes.size}"– page[:vote_score].visual_effect :highlight
RJS Templates
24
25
class VotesController < ApplicationController
def create
@story = Story.find(params[:story_id])
@story.votes.create
respond_to do |format|
format.html { redirect_to @story }
format.js
end
end
end
What if the browser does not supports Ajax?
26
• Deal with parts of the page constantly reused
• Eg a voting history
What’s a partial?
27
<h2>
<span id="vote_score">
Score: <%= @story.votes.size %>
</span>
<%= @story.name %>
</h2>
<ul id="vote_history">
<% if @story.votes.empty? %>
<em>No votes yet!</em>
<% else %>
<%= render :partial => 'votes/vote',
:collection => @story.votes %>
<% end %>
</ul>
<p>
<%= link_to @story.link, @story.link %>
</p>
<div id="vote_form">
<% form_remote_tag :url => story_votes_path(@story) do %>
<%= submit_tag 'shove it' %>
<% end %>
</div>
Let’s add a voting history!stories./show.html.erb
28
</h2>
<ul id="vote_history">
<% if @story.votes.empty? %>
<em>No votes yet!</em>
<% else %>
<%= render :partial => 'votes/vote',
:collection => @story.votes %>
<% end %>
</ul>
<p>
Let’s add a voting history!stories./show.html.erb
29
• Views/votes/_vote.html.erb
<li><%= vote.created_at.to_formatted_s(:short) %></li>
• Notes: short => "%d %b %H:%M"
Create a partial
30
• Create.js
page.replace_html 'vote_score', "Score: #{@story.votes.size}"
page[:vote_score].visual_effect :highlight
page[:vote_history].replace_html :partial => 'vote',
:collection => @story.votes
Updating the history during a vote
31
• Start a server– ruby script/server
• Goto– http://127.0.0.1:3000/stories/1
Let’s see what we have so far ...
32
Questions?