2012-04-22 60 views
1

所以我寫了一個基本的成員修改操作,我想,讓我們保持乾爽,只是修改params散列,然後傳遞給我們的update方法,但它似乎不工作。我想有一些軌道魔法會發生,我無法找到...從我讀過的這個應該可以工作。我正在使用Rails 3.2。如何從rails 3中的其他操作調用更新操作?

這裏是什麼,我試圖做一個例子:

# POST /tasks/1/toggle_done 
    def toggle_done 
    @task = Task.find(params[:id]) 
    puts "<<<<<", params 

    # invert done bool value 
    params[:done] = !(@task.done) 

    # thought maybe update_attributes retured a full set of 
    # attributes in the params... 
    #params[:name] = @task.name + "...test." 

    # thought maybe the method call to update was getting 
    # filtered or something. Doesn't seem to help. 
    #params[:_method] = "put" 
    # redirect to update with these new params 

    puts ">>>>>", params 

    # Why bother rewriting task.done = x; task.save; 
    # redirect_to show; etc when update already does that. 
    update 
    end 

    # PUT /tasks/1 
    # PUT /tasks/1.json 
    def update 
    @task = Task.find(params[:id]) 

    puts "======", params 

    respond_to do |format| 
     if @task.update_attributes(params[:task]) 
     format.html { redirect_to @task, notice: 'Task was successfully updated.' } 
     format.json { head :no_content } 
     else 
     format.html { render action: "edit" } 
     format.json { render json: @task.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

我得到以下控制檯輸出:

<<<<< 
{"_method"=>"post", "authenticity_token"=>"CVqzsJfSVgM7Bq/kXlrjzkWVoA7Pbne4GNEHqbQB42s=", "action"=>"toggle_done", "controller"=>"tasks", "id"=>"1"} 
>>>>> 
{"_method"=>"put", "authenticity_token"=>"CVqzsJfSVgM7Bq/kXlrjzkWVoA7Pbne4GNEHqbQB42s=", "action"=>"toggle_done", "controller"=>"tasks", "id"=>"1", "done"=>false, "name"=>"Put Done button in index view...test."} 
====== 
{"_method"=>"put", "authenticity_token"=>"CVqzsJfSVgM7Bq/kXlrjzkWVoA7Pbne4GNEHqbQB42s=", "action"=>"toggle_done", "controller"=>"tasks", "id"=>"1", "done"=>false, "name"=>"Put Done button in index view...test."} 

所以它看起來像陣列設置權PARAMS。它呈現閃爍消息「任務已成功更新」的常規show視圖,因此看起來好像整個方法得到執行,但模型屬性的非模型屬性發生了變化。我想在update_attributes裏面的東西是失敗的。任何人都可以爲我闡明這一點嗎?

這是一個瘋狂的事情嗎?我是否應該在toggle_done方法中設置並保存,而不是鏈接更新?

回答

3

Rails將任務對象的屬性保存在散列params[:task]中。因此,您在toggle_done方法中需要將結果保存在params[:task][:done]中否則,rails無法將done屬性與任務相關聯。

def toggle_done 
    @task = Task.find(params[:id]) 
    params[:task] = { done: !(@task.done) } 
    update 
end 

但隨着調用Update方法您在何處時只有2個neccessary 3個數據庫查詢 - 而前2相同且因爲你在toggle_done方法的ID以及在update加載任務。

爲了避免這種情況,您可以將保存和重定向部分放入受保護的方法中,並在您想保存時調用它。像這樣:

def toggle_done 
    @task = Task.find(params[:id]) 
    params[:task] = { done: !(@task.done) } 
    save_updated 
end 

def update 
    @task = Task.find(params[:id]) 
    save_updated 
end 

protected 
def save_updated 
    respond_to do |format| 
     if @task.update_attributes(params[:task]) 
     format.html { redirect_to @task, notice: 'Task was successfully updated.' } 
     format.json { head :no_content } 
     else 
     format.html { render action: "edit" } 
     format.json { render json: @task.errors, status: :unprocessable_entity } 
     end 
end 
2

您正在將params [:task]傳遞給update_attributes,這不存在。試試:

params[:task] = {:done => !(@task.done)} 
+0

Doh。顯然沒有引起足夠的重視。我想我的問題仍然存在,這是否是合法的「軌道方式」? – Soup 2012-04-22 14:45:12

+0

我想這只是像你這樣做,但正如我在我的回答中指出的那樣,您正在提出更多的數據庫請求。 – klump 2012-04-22 14:47:14

+0

因此,DRY的方式是將通用代碼放入自己的方法中,然後調用它們。 – klump 2012-04-22 14:53:07