如何更新 Rails 中的所有关联模型?

How to update all associated models in Rails?

我正在使用 Rails 和 React。我有两个模型:scheduleworkerworker belongs_to scheduleschedule has_many workers。我想从 React 向 rails 发出更新请求。

这是我用来发送请求的 fetch 函数的样子:

function updateSchedule(scheduleId, date, message, workersArray, cb){
  return fetch(`api/schedules/${scheduleId}`, {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      date: date,
      message: message,
      user_id: 1,
      worker_info: workersArray
    })
  }).then((response) => response.json())
    .then(cb);
}

workersArray 样本:

[{"id"=>54, "name"=>"Owen
 Johnston", "phone"=>"111-222-3333", "created_at"=>"2017-06-13T22:17:45.769Z", "updated_at"=>"2017-06-13T22:17:45.769Z", "schedule_id"=>33}, {"id"=
>55, "name"=>"Mary Watson", "phone"=>"123-456-7890", "created_at"=>"2017-06-13T22:17:45.778Z", "updated_at"=>"2017-06-13T22:17:45.778Z", "schedule_
id"=>33}]

日程表有日期、消息和 user_id 属性。时间表也有一组特定的工人。每个工人都有一个 namephone。简而言之,在特定的时间表上,我想更新时间表的属性,包括所有工人姓名和其中的 phone 。我在遍历属于该计划的所有工作人员并更新每个工作人员的参数时遇到问题。

这是大意。我在使 update 方法工作时遇到问题。

  def update
    @schedule = Schedule.find(params[:id])
    if @schedule.update_attributes(schedule_params)
      worker_params["worker_info"].each do |w|
        @worker = Worker.find(w.id)
        @worker.update_attributes!
      end
      render json: @schedule
    else
      render json: @schedule, status: :unprocessable_entity
    end
  end

...
  def schedule_params
    params.require(:schedule).permit(:date, :message, :user_id)
  end


  def worker_params
    params.permit(worker_info: [:name, :phone])
  end

我如何从 React 向 rails 发送放置请求并告诉 Rails 更新计划以及与计划关联的所有工作人员?

尽管我发现您发送给 rails 的内容存在差异,但我们假设您发送的参数正确并且能够更新计划(但不能更新工作人员)。差异在于您没有在参数中发送 schedule 键,而是在这一行中要求它:

params.require(:schedule).permit(:date, :message, :user_id)

确保您的最终 JSON(您发送到 rails)是这样的:

{
  "schedule": {
    "date": "...your date",
    "message": "...message",
    "user_id": "...user_id"
  }
}

来到我认为的实际问题是无法更新工作人员。 Rails 有一个特殊的模型指令,可以减轻您的痛苦。

在您的 Schedule 模型中,写入:

accepts_nested_attributes_for :workers, allow_destroy: true

这将使模型也能够更新其子属性。之后你的控制器需要稍微改变一下。

def schedule_params
  params.require(:schedule).permit(:date, :message, :user_id, workers_attributes: [:id, :name, :phone, :_destroy])
end

然后使用@schedule.update_attributes(schedule_params)更新时间表,以及工人。

你的最终 JSON 应该是这样的:

{
  "schedule": {
    "date": "...your date",
    "message": "...message",
    "user_id": "...user_id",
    "workers_attributes": [{
      "id": 123,
      "name: "...name",
      "phone": "...phone"
    }]
  }
}

您可以传递一组工人的属性,这将定义您是否要 add/update/delete 与时间表相关的工人。在继续之前,您可能需要阅读有关 accepts_nested_attributes_for 的更多信息。