320 likes | 461 Views
Web Science Stream. Web 2.0. Web 2.0. We’ll implement a voting mechanism Using AJAX. Creating the vote model. ruby script/generate model Vote story_id:integer. The vote migration. class CreateVotes < ActiveRecord ::Migration def self.up create_table :votes do |t|
E N D
Web Science Stream Web 2.0
Web 2.0 • We’ll implement a voting mechanism • Using AJAX
Creating the vote model • ruby script/generate model Vote story_id:integer
The vote migration 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
Apply the migration • rake db:migrate
More on relationships • 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
Let’s test it ... • ruby script/console s = Story.find(:first) s.votes s.votes.create s.votes.size
Finalising the relationship • App/models/vote.rb • Add • belongs_to :story • Use the reload! command in the console • Try • v = Vote.find(:first) • v.story
Showing our stories 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
Displaying the stories! • App/views/stories/show.html.erb <h2><%= @story.name %></h2> <p><%= link_to @story.link, @story.link %></p>
Let’s see what we have so far ... • Start a server • ruby script/server • Goto • http://127.0.0.1:3000/stories/1
Better randomization • Change the index.html to A random link: <%= link_to @story.name, story_path(@story) %>
Let’s create the votes • Generate • ruby script/generate controller Votes create • Arrange the routes • Routes.rb • map.resources :stories, :has_many => :votes • Create the routes • rake routes
Looking at the rake routes Nested routes of the form ... /stories/:story_id/votes /stories/1/votes
Ajax • 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)
Rails + Ajax • 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/
Some features of script.aculo.us 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
Adding the JavaScript libraries • 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
Modifying the stories/show.html.erb <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>
Adding some styles #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_forminput:hover { background-color: #aea; }
Let’s see what we have so far ... • Start a server • ruby script/server • Goto • http://127.0.0.1:3000/stories/1
Adding votes class VotesController < ApplicationController def create @story = Story.find(params[:story_id]) @story.votes.create end end
RJS Templates • 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
What if the browser does not supports Ajax? 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’s a partial? • Deal with parts of the page constantly reused • Eg a voting history
Let’s add a voting history!stories./show.html.erb <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 </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>
Create a partial • Views/votes/_vote.html.erb <li><%= vote.created_at.to_formatted_s(:short) %></li> • Notes: short => "%d %b %H:%M"
Updating the history during a vote • 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
Let’s see what we have so far ... • Start a server • ruby script/server • Goto • http://127.0.0.1:3000/stories/1