320 likes | 468 Vues
This guide covers the implementation of a voting mechanism in a Ruby on Rails application using AJAX. It demonstrates how to create a Vote model, establish relationships with stories, and build a responsive user interface that allows users to cast votes without page reloads. Learn to set up Rails routes, controllers, and views, as well as utilize AJAX for seamless user interactions. By following this tutorial, you'll gain hands-on experience in building dynamic web applications that enhance user engagement.
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