Created
November 6, 2011 19:40
-
-
Save simaob/1343364 to your computer and use it in GitHub Desktop.
Ordering records through index page record with AJAX (powered by jQuery) in a Ruby on Rails 3.1 App
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%#PATH: app/views/products/ %> | |
<% if !product.first? %> | |
<%= link_to image_tag("ordering_icons/up.gif", :alt => "up", :title => "Move up"), move_up_product_path(product), :method => :put, :remote => true %> | |
<% end %> | |
<% if !product.last? %> | |
<%= link_to image_tag("ordering_icons/down.gif", :alt => "down", :title => "Move down"), move_down_product_path(product), :method => :put, :remote => true %> | |
<% end %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#PATH: db/migrate/ | |
class AddSortIndexToProducts < ActiveRecord::Migration | |
def self.up | |
add_column :products, :sort_index, :integer | |
end | |
def self.down | |
remove_column :products, :sort_index | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%#PATH: app/views/products/ %> | |
<h1>Products</h1> | |
<p><%= link_to "New Product", new_product_path %></p> | |
<table> | |
<thead> | |
<tr> | |
<th></th> | |
<th>Name</th> | |
<th>Price</th> | |
</tr> | |
</thead> | |
<tbody> | |
<% @products.each do |product| %> | |
<tr id="product_#{product.id}"> | |
<td id="product_#{product.id}_sort"> | |
<%= render :partial => "ordering", :locals => {:product => product} %> | |
</td> | |
<td><%= product.name %></td> | |
<td><%= product.price %></td> | |
</tr> | |
<% end %> | |
</tbody> | |
</thead> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%#PATH: app/views/products/ %> | |
$(function(){ | |
<% if @success %> | |
$("#product_<%[email protected]%>").next().after($("#product_<%[email protected]%>")); | |
$("#product_<%[email protected]%>_sort").html("<%= escape_javascript(render :partial => "ordering", :locals => {:product => @product} ) %>"); | |
$("#product_<%[email protected]%>_sort").html("<%= escape_javascript(render :partial => "ordering", :locals => {:product => @product.previous} ) %>"); | |
<% else %> | |
alert("It wasn't possible to move the product. The last product can't be moved further down...") | |
<% end %> | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%#PATH: app/views/products/ %> | |
$(function(){ | |
<% if @success %> | |
$("#product_<%[email protected]%>").prev().before($("#product_<%[email protected]%>")); | |
$("#product_<%[email protected]%>_sort").html("<%= escape_javascript(render :partial => "ordering", :locals => {:product => @product} ) %>"); | |
$("#product_<%[email protected]%>_sort").html("<%= escape_javascript(render :partial => "ordering", :locals => {:product => @product.next} ) %>"); | |
<% else %> | |
alert("It wasn't possible to move the product. The first product can't be moved further up...") | |
<% end %> | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#PATH: app/models/ | |
class Product < ActiveRecord::Base | |
attr_accessible :sort_index, :name, :price | |
before_create :set_sort_index | |
def last? | |
self.sort_index == Product.maximum('sort_index') | |
end | |
def first? | |
self.sort_index == 0 | |
end | |
def next | |
Product.where(:sort_index => (self.sort_index+1)).first | |
end | |
def previous | |
Product.where(:sort_index => (self.sort_index-1)).first | |
end | |
def move_up | |
switched = Product.where(:sort_index => (self.sort_index - 1)).first | |
return false if !switched | |
switched.sort_index = self.sort_index | |
self.sort_index -= 1 | |
switched.save | |
self.save | |
end | |
def move_down | |
switched = Product.where(:sort_index => (self.sort_index + 1)).first | |
return false if !switched | |
switched.sort_index = self.sort_index | |
self.sort_index += 1 | |
switched.save | |
self.save | |
end | |
private | |
def set_sort_index | |
current_max_index = Product.maximum('sort_index') || -1 | |
self.sort_index = current_max_index+1 | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#PATH: spec/models/ | |
require 'spec_helper' | |
describe 'setting and updating product sort_index value' do | |
it "should set the sort_index value to zero for the first product, and then increment the sort_index value for the following records" do | |
#no products | |
Product.all.count.should == 0 | |
#create a product | |
product = Product.create | |
Product.all.count.should == 1 | |
product.sort_index.should == 0 | |
#create another product | |
product1 = Product.create | |
Product.all.count.should == 2 | |
product1.sort_index.should == 1 | |
#create another product | |
product2 = Product.create | |
Product.all.count.should == 3 | |
product2.sort_index.should == 2 | |
end | |
it "should respond true to first? and last? if there's only a product and it has sort_index value of 0" do | |
product = Product.create | |
product.first?.should == true | |
product.last?.should == true | |
product.sort_index.should == 0 | |
end | |
it "responds true to the method first? and false to the method last? when called on a product with sort_index 0, and when there is a second product with sort_index value 1" do | |
product = Product.create | |
product1 = Product.create | |
product.first?.should == true | |
product.last?.should == false | |
product.sort_index.should == 0 | |
product1.first?.should == false | |
product1.last?.should == true | |
product1.sort_index.should == 1 | |
end | |
it "responds false to both first? and last? when called on a product with sort_index 1, and there are other designations of the same level with sort_index 0 and 2" do | |
product = Product.create | |
product1 = Product.create | |
product2 = Product.create | |
product.first?.should == true | |
product.last?.should == false | |
product.sort_index.should == 0 | |
product1.first?.should == false | |
product1.last?.should == false | |
product1.sort_index.should == 1 | |
product2.first?.should == false | |
product2.last?.should == true | |
product2.sort_index.should == 2 | |
end | |
it "should return the product with sort_index+1 when calling next on a product. it should return nil if there isn't another product" do | |
product = Product.create | |
product.next.should == nil | |
product.previous.should == nil | |
product1 = Product.create | |
product.next.should == product1 | |
product1.sort_index.should == product.sort_index+1 | |
product1.previous.should == product | |
end | |
#Order hierarchy: 0, 1, 2, ... | |
it "should increase the sort_index of a product when moving it down, and increase it when moving up, updating the other products accordingly" do | |
product = Product.create | |
product1 = Product.create | |
product2 = Product.create | |
product.sort_index.should == 0 | |
product1.sort_index.should == 1 | |
product2.sort_index.should == 2 | |
product.move_down | |
product.reload | |
product1.reload | |
product2.reload | |
product.sort_index.should == 1 | |
product1.sort_index.should == 0 | |
product2.sort_index.should == 2 | |
product.move_down | |
product.reload | |
product1.reload | |
product2.reload | |
product.sort_index.should == 2 | |
product1.sort_index.should == 0 | |
product2.sort_index.should == 1 | |
product.move_down | |
product.reload | |
product1.reload | |
product2.reload | |
product.sort_index.should == 2 | |
product1.sort_index.should == 0 | |
product2.sort_index.should == 1 | |
product.move_up | |
product.reload | |
product1.reload | |
product2.reload | |
product.sort_index.should == 1 | |
product1.sort_index.should == 0 | |
product2.sort_index.should == 2 | |
product.move_up | |
product.reload | |
product1.reload | |
product2.reload | |
product.sort_index.should == 0 | |
product1.sort_index.should == 1 | |
product2.sort_index.should == 2 | |
product.move_up | |
product.reload | |
product1.reload | |
product2.reload | |
product.sort_index.should == 0 | |
product1.sort_index.should == 1 | |
product2.sort_index.should == 2 | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#PATH: app/controllers/ | |
class ProductsController < ApplicationController | |
respond_to :html, :js | |
def index | |
@products = Product.order("sort_index ASC") | |
end | |
def move_up | |
@product = Product.find(params[:id]) | |
@success = [email protected]? && @product.move_up | |
end | |
def move_down | |
@product = Product.find(params[:id]) | |
@success = [email protected]? && @product.move_down | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#PATH: config/ | |
YourApplication::Application.routes.draw do | |
resources :products do | |
member do | |
put :move_up | |
put :move_down | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment