Iggy
Iggy

Reputation: 5251

How to update all associated models in Rails?

I am using Rails and React. I have two models: schedule and worker. worker belongs_to schedule and schedule has_many workers. I want to make an update request to rails from react.

This is what the fetch function looks like that I use to send the request:

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);
}

sample of 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}]

Schedule has date, message, and user_id attributes. Schedule also has a specific group of workers. Each worker has a name and phone. In short, on a specific schedule, I want to update the schedule's properties, including all the workers name and phone in it. I am having problem iterating through all the workers belonging in that schedule and updating parameters of each worker.

This is the general idea. I am having problem making update method to work.

  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

How can I send a put request from react to rails and tell Rails to update the schedule and all the workers associated to the schedule?

Upvotes: 1

Views: 1112

Answers (1)

31piy
31piy

Reputation: 23859

Although I see a discrepancy in what you're sending to rails, let's assume that you're sending correct parameters and are able to update schedule (but not workers). The discrepancy is that you're not sending schedule key in your params, but requiring it in this line:

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

Make sure that your final JSON (which you're sending to rails) is something like this:

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

Coming to the actual problem, which I believe, is not being able to update workers. Rails has a special directive for models which will ease your pain.

In your Schedule model, write:

accepts_nested_attributes_for :workers, allow_destroy: true

This will enable the model to update its child attributes as well. Your controller needs to change a bit after this.

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

Then use @schedule.update_attributes(schedule_params) to update the schedule, as well as the workers.

Your final JSON should look like:

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

You can pass an array of workers' attributes, which will define if you want to add/update/delete workers related to a schedule. You may want to read more about accepts_nested_attributes_for before proceeding.

Upvotes: 2

Related Questions