After ajax update and destroy


#1

問題我用ajax 送了我的request(update and destroy)都有成功,但是controller 去跑後

def update
  if @event.update(params)
    redirect_to root_path
  end 
end

在devTool會回404 not found

server log 如下

Redirected to http://localhost:3000/
Completed 302 Found in 4ms (ActiveRecord: 1.1ms)

Started PUT “/” for 127.0.0.1 at 2014-10-02 14:05:06 +0800

ActionController::RoutingError (No route matches [PUT] “/”):

我大概知道因為他送過來的是put 所以他用這個需求再去找,

現在不知道該如何去改,應該在ajax success在call 一個方法去get

還是我的邏輯判斷哪邊不對??


#2

首先,AJAX系列不能用 redirect_to,否則該 request 會轉到下站,並把下站的 response 抓回 JavaScript ,這通常都不是你要的,所以請在 action 下面使用類似

render :json => {:success => "okay"} #成功
render :json => {:error => 'fail'  } #失敗

然後再從 JavaScript 端做判斷 return 回來的 data 之類的

再來,你前端的方式是有問題的,我沒看過你的 code 所以不確定你丟的是 form 的 post ( put ) 還是 ajax 來的封包之類的 ( 通常不會跳下一頁 ),而…我做 jQuery 的 $.ajax 的解釋好了,然而下面的這些其實 doc 內

http://api.jquery.com/jquery.ajax/

都有寫的,所以我寫常用的項目

jQuery.ajax( url , {
  async : [true | false] , //是否啟用async模式(false會停住等待回傳)
  data : [String / Object / Array] , //post要傳入的資料,可接form serialize()和obj
  dataType : [json | text] , //回傳的資料格式,常用的是這兩個,還有其他的
  type : [GET | POST | DELETE | PUT | PATCH], //用這邊對你的route
  success : function(data){...} //成功後要做啥,和$.get / $.post後面接的function相同
  error : function(){...} //出錯了要做啥
});

所以要發一個PUT封包,因為沒有方便的方法,所以如上表,最簡單的方式會是

jQuery.ajax( url , {
  async : false ,
  data : $.find("form").serialize() , //把來源form包成一大票params的url
  dataType : 'json' , 
  type : 'PUT' , 
  success : function(data){
    console.log('success <3' , data)
  } ,
  error : function(){
    console.log('error :(')
  }
});

anyway這邊會建議你多玩看看就是了,看你家瀏覽器dev tool的network發出去的封包是不是你所期待的,才去看rails log怎麼跑,有因才有果,得到那個果在看怎麼處理,有的沒的


#3

請問JC大,

從 console 的地方可以看到我已經從 message create 那邊接到我想要的資料了,
可是,在 show page 這邊都會顯示出來 @mesage 是 nil 的錯誤訊息,是因為 javascript 這邊不能夠寫 partial嗎?

	$('.add_message').prepend('<%= j render partial: "dashboard/messages/message", locals: {message: @message } %>');

以下是全部的code:

	$("#newMessage").on("submit", function(event) {
	event.preventDefault();
	var conversation_id = document.getElementById("new_message").getAttribute('data-conversation-id');
	$.ajax({
		url: conversation_id + "/messages",
		method: "POST",
		dataType: "json",
		data: { 
			message: { 
				content: $("#message_content").val()
			}
		},
		success: function(response, status) {
			console.log(response);
			$('.add_message').prepend('<%= j render partial: "dashboard/messages/message", locals: {message: @message } %>');
			modal.style.display = "none";
			$('#message_content').val('');
		},
		error: function(response, status) {
			console.log(status);
		}
	});
});

github:


#4

你是不是把 … partial 想得太萬能了?且這種需求應該都丟 AJAX 會好點唄,寫這種 code 出去通常都會出事的啊 …

你的前面明明就有一層 ajax 了,後面再一層 ajax 不就好了? 不然就把前面那層 ajax 的輸出一同包裝,兩份資料集合包成一包,那就不用第二個 ajax 哩

再來,去玩一下 vue.js 或是 jQuery 也有的 template engine,這樣你就可以只傳 data 不用傳整份 HTML layout 出來,否則你的東西很容易被 XSS 的

大概這樣唄,有問題再提出哩


#5

找到解法了,只是應該會像JC大說的被XSS吧?

message_controller

def create
    @conversation = Conversation.find_by(:id => params[:conversation_id])
    @message = @conversation.message.build(message_params)
    @message.sender_id = current_user.id
    @message.recipient_id = @conversation.recipient_id 
   
      if @message.save
          render json: {
          html_data: render_to_string(partial: 'dashboard/messages/message', locals: { message: @message })
        }
      else
      end
    end

show.erb.html

	$("#newMessage").on("submit", function(event) {
	event.preventDefault();
	var conversation_id = document.getElementById("new_message").getAttribute('data-conversation-id');
	$.ajax({
		url: conversation_id + "/messages",
		method: "POST",
		dataType: "json",
		data: { 
			message: { 
				content: $("#message_content").val()
			}
		},
		success: function(response, status, xhr) {	
			$('.add_message').prepend(response.html_data);
			modal.style.display = "none";
			$('#message_content').val('');
		},
		error: function(response, status) {
			console.log(status);
		}
	});
});

#6

yep~ 這樣至少好點,其實我後來有想到一招我以前常用的忘記寫出來 …

其實你只需要先寫在原先的 HTML 內,然後不顯示,ajax 取得資料後才顯示即可,這樣你也可以不用 render_to_string & 一樣可以用 partial … (( 想說感覺怪怪的哪裡不正確 … 最近太少寫 view 的東西了 X"D


#7

我是在這個網站找到解法的:

雖然版主的第二個方法有人給了提示,但是沒有正式的解答。
運氣好,被我自己試出來了,加個:formats => [:html],就好了:

respond_to do |format|
      if @message.save
         format.json { 
          render json:{
            html_data: render_to_string(partial: 'dashboard/messages/message',:formats => [:html], locals: {message: @message})
          }
        }
      else
        format.json { render json: @message.errors, status: :unprocessable_entity }
      end
    end