Hi,
I'm having a very strange problem using a AJAX sortable list containing images for articles. I tried a lot of things and searched for hours but I don't find the reason. I would really appreciate your help. Please excuse my deficient english, I'm from Berlin. I try to explain the situation as clear as possible. If you need any further info, just drop a note.
The idea: User can post articles and add comments and images (assets) to each article. So every article has many comments and assets. I'm using restful routing and AJAX for image uploading, deleting and adding comments etc. without any problems.
The problem: When I try to reorder the images, all the information is saved, but then the index action of the controller is called again. So the page reloads. But I'm using Ajax to prevent this. If I have for example a form on the page with unsaved information, all user input is lost and the page is refreshed with the data from the DB.
The Routing: To access the assets of an article (e.g. ID 3) I call /articles/3/ assets .
My routes.rb looks like this (partial):
map.resources :articles, :member => {:publish => :get} do |article| article.resources :comments do |comment| comment.resources :comments end
article.resources :assets, :collection => {:saveorder => :post} end
rake routes shows me for the articles the following routes: articles GET / articles {:action=>"index", :controller=>"articles"} formatted_articles GET / articles.:format {:action=>"index", :controller=>"articles"} POST / articles {:action=>"create", :controller=>"articles"} POST / articles.:format {:action=>"create", :controller=>"articles"} new_article GET /articles/ new {:action=>"new", :controller=>"articles"} formatted_new_article GET /articles/ new.:format {:action=>"new", :controller=>"articles"} edit_article GET /articles/:id/ edit {:action=>"edit", :controller=>"articles"} formatted_edit_article GET /articles/:id/ edit.:format {:action=>"edit", :controller=>"articles"} publish_article GET /articles/:id/ publish {:action=>"publish", :controller=>"articles"} formatted_publish_article GET /articles/:id/ publish.:format {:action=>"publish", :controller=>"articles"} article GET / articles/:id {:action=>"show", :controller=>"articles"} formatted_article GET / articles/:id.:format {:action=>"show", :controller=>"articles"} PUT / articles/:id {:action=>"update", :controller=>"articles"} PUT / articles/:id.:format {:action=>"update", :controller=>"articles"} DELETE / articles/:id {:action=>"destroy", :controller=>"articles"} DELETE / articles/:id.:format {:action=>"destroy", :controller=>"articles"} article_comments GET /articles/:article_id/ comments {:action=>"index", :controller=>"comments"} formatted_article_comments GET /articles/:article_id/ comments.:format {:action=>"index", :controller=>"comments"} POST /articles/:article_id/ comments {:action=>"create", :controller=>"comments"} POST /articles/:article_id/ comments.:format {:action=>"create", :controller=>"comments"} new_article_comment GET /articles/:article_id/ comments/new {:action=>"new", :controller=>"comments"} formatted_new_article_comment GET /articles/:article_id/ comments/new.:format {:action=>"new", :controller=>"comments"} edit_article_comment GET /articles/:article_id/ comments/:id/edit {:action=>"edit", :controller=>"comments"} formatted_edit_article_comment GET /articles/:article_id/ comments/:id/edit.:format {:action=>"edit", :controller=>"comments"} article_comment GET /articles/:article_id/ comments/:id {:action=>"show", :controller=>"comments"} formatted_article_comment GET /articles/:article_id/ comments/:id.:format {:action=>"show", :controller=>"comments"} PUT /articles/:article_id/ comments/:id {:action=>"update", :controller=>"comments"} PUT /articles/:article_id/ comments/:id.:format {:action=>"update", :controller=>"comments"} DELETE /articles/:article_id/ comments/:id {:action=>"destroy", :controller=>"comments"} DELETE /articles/:article_id/ comments/:id.:format {:action=>"destroy", :controller=>"comments"} article_comment_comments GET /articles/:article_id/ comments/:comment_id/comments {:action=>"index", :controller=>"comments"} formatted_article_comment_comments GET /articles/:article_id/ comments/:comment_id/comments.:format {:action=>"index", :controller=>"comments"} POST /articles/:article_id/ comments/:comment_id/comments {:action=>"create", :controller=>"comments"} POST /articles/:article_id/ comments/:comment_id/comments.:format {:action=>"create", :controller=>"comments"} new_article_comment_comment GET /articles/:article_id/ comments/:comment_id/comments/new {:action=>"new", :controller=>"comments"} formatted_new_article_comment_comment GET /articles/:article_id/ comments/:comment_id/comments/new.:format {:action=>"new", :controller=>"comments"} edit_article_comment_comment GET /articles/:article_id/ comments/:comment_id/comments/:id/edit {:action=>"edit", :controller=>"comments"} formatted_edit_article_comment_comment GET /articles/:article_id/ comments/:comment_id/comments/:id/edit.:format {:action=>"edit", :controller=>"comments"} article_comment_comment GET /articles/:article_id/ comments/:comment_id/comments/:id {:action=>"show", :controller=>"comments"} formatted_article_comment_comment GET /articles/:article_id/ comments/:comment_id/comments/:id.:format {:action=>"show", :controller=>"comments"} PUT /articles/:article_id/ comments/:comment_id/comments/:id {:action=>"update", :controller=>"comments"} PUT /articles/:article_id/ comments/:comment_id/comments/:id.:format {:action=>"update", :controller=>"comments"} DELETE /articles/:article_id/ comments/:comment_id/comments/:id {:action=>"destroy", :controller=>"comments"} DELETE /articles/:article_id/ comments/:comment_id/comments/:id.:format {:action=>"destroy", :controller=>"comments"} saveorder_article_assets POST /articles/:article_id/ assets/saveorder {:action=>"saveorder", :controller=>"assets"} formatted_saveorder_article_assets POST /articles/:article_id/ assets/saveorder.:format {:action=>"saveorder", :controller=>"assets"} article_assets GET /articles/:article_id/ assets {:action=>"index", :controller=>"assets"} formatted_article_assets GET /articles/:article_id/ assets.:format {:action=>"index", :controller=>"assets"} POST /articles/:article_id/ assets {:action=>"create", :controller=>"assets"} POST /articles/:article_id/ assets.:format {:action=>"create", :controller=>"assets"} new_article_asset GET /articles/:article_id/ assets/new {:action=>"new", :controller=>"assets"} formatted_new_article_asset GET /articles/:article_id/ assets/new.:format {:action=>"new", :controller=>"assets"} edit_article_asset GET /articles/:article_id/ assets/:id/edit {:action=>"edit", :controller=>"assets"} formatted_edit_article_asset GET /articles/:article_id/ assets/:id/edit.:format {:action=>"edit", :controller=>"assets"} article_asset GET /articles/:article_id/ assets/:id {:action=>"show", :controller=>"assets"} formatted_article_asset GET /articles/:article_id/ assets/:id.:format {:action=>"show", :controller=>"assets"} PUT /articles/:article_id/ assets/:id {:action=>"update", :controller=>"assets"} PUT /articles/:article_id/ assets/:id.:format {:action=>"update", :controller=>"assets"} DELETE /articles/:article_id/ assets/:id {:action=>"destroy", :controller=>"assets"} DELETE /articles/:article_id/ assets/:id.:format {:action=>"destroy", :controller=>"assets"}
Please note that I'm using acts_as_tree for the comments to enable replys.
My Controller: class AssetsController < ApplicationController
make_resourceful do actions :show, :new, :edit, :update, :destroy belongs_to :article
before :new do @comment.user = current_user end end
def index if params[:article_id].nil? @assets = Asset.find(:all, :conditions => {:parent_id => nil}, :order => 'order_number ASC') else @assets = Asset.find(:all, :conditions => {:parent_id => nil, :article_id => params[:article_id]}, :order => 'order_number ASC') end respond_to do |format| format.html # index.rhtml format.xml { render :xml => @assets.to_xml } format.js end end
# This is the action which is called by sortable_element def saveorder params[:assetlist].each_with_index do |id, position| asset = Asset.find(id) asset.update_attribute('order_number', position) end respond_to do |format| format.js {render :nothing => true} end end
end
My views (I'm using partials and HAML):
# First the index.haml
%h1= _("Listing assets") %ul#assetlist =render :partial => @assets =render :partial => 'form' =sortable_element("assetlist", :url => saveorder_article_assets_path)
# Than the _asset.haml partial
%li{:id => "asset_#{asset.id}"} = link_to(image_tag(asset.public_filename(:thumb))) if asset.image? = link_to(asset.filename, article_assets_path(asset)) = link_to_remote _("Delete"), :url => article_assets_path(asset), :confirm => _('Are you sure?'), :method => :delete
# the form partial is just for uploading and works perfectly well, so I guess it's not interesting here
And last but not least the Mongrel Server output in the console. Please note that after the action saveorder the index action is called again -> the problem.