1

所以我正在编写一个基本的成员修改操作,我想,让我们保持 DRY 并只修改参数哈希然后传递给我们的update方法,但它似乎不起作用。我想有一些我找不到的 Rails 魔术......从我读过的内容来看,这应该有效。我正在使用 Rails 3.2。

这是我正在尝试做的一个例子:

  # 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 数组设置正确。它使用 Flash 消息“任务已成功更新。”呈现常规show视图,因此看起来整个方法都已执行,但没有任何模型属性发生更改。我猜 update_attributes 里面的东西失败了。任何人都可以为我阐明这一点吗?

这也是一件疯狂的事情吗?我应该在我的 toggle_done 方法中设置和保存而不是链接更新吗?

4

2 回答 2

3

Rails 将任务对象的属性保存在 hash 中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 方法,您可以进行 3 个数据库查询,其中只有 2 个是必需的 - 前 2 个是相同的,因为您在toggle_done方法和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
于 2012-04-22T14:42:17.980 回答
2

您将 params[:task] 传递给不存在的 update_attributes。尝试:

params[:task] = {:done => !(@task.done)}
于 2012-04-22T14:37:43.003 回答