如何从rails 3中的其他操作调用更新操作?
问题描述:
所以我写了一个基本的成员修改操作,我想,让我们保持干爽,只是修改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方法中设置并保存,而不是链接更新?
答
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
答
您正在将params [:task]传递给update_attributes,这不存在。试试:
params[:task] = {:done => !(@task.done)}
Doh。显然没有引起足够的重视。我想我的问题仍然存在,这是否是合法的“轨道方式”? – Soup 2012-04-22 14:45:12
我想这只是像你这样做,但正如我在我的回答中指出的那样,您正在提出更多的数据库请求。 – klump 2012-04-22 14:47:14
因此,DRY的方式是将通用代码放入自己的方法中,然后调用它们。 – klump 2012-04-22 14:53:07