Невозможно передать отношения многие ко многим методу Create - PullRequest
0 голосов
/ 27 апреля 2019

Возможно, прошло слишком много времени с тех пор, как я использовал Rails, но я не могу понять, почему это работает (создание Task и затем присвоение prerequisites с использованием #prerequisite_ids=):

[3] pry(main)> task = Task.create(name:"do this last")                                                                                                                               
=> #<Task:0x00007fb0e2570860
 id: 7,
 name: "do this last",
  ...>
[4] pry(main)> task.prerequisite_ids=[5,6]                                                                                                                                           
=> [5, 6]
[5] pry(main)> task.prerequisites                                                                                                                                                    
=> [#<Task:0x00007fb0e2a82948
  id: 5,
  name: "Do this first",
  ...>
 #<Task:0x00007fb0e2a82600
  id: 6,
  name: "Do this next",
  ...>]

Но это не так (передача массива prerequisite_ids в Task.create)

[1] pry(main)> t = Task.create(name:"do this last", prerequisite_ids:[5,6])                                                                                                          
  Task Load (1.3ms)  SELECT "tasks".* FROM "tasks" WHERE "tasks"."id" IN ($1, $2)  [["id", 5], ["id", 6]]
   (0.3ms)  BEGIN
   (0.2ms)  ROLLBACK
=> #<Task:0x00007fb0e0e93d40 id: nil, name: "do this last", description: nil, created_at: nil, updated_at: nil, completed: false>
[2] pry(main)> t.errors                                                                                                                                                              
=> #<ActiveModel::Errors:0x00007fb0e2b18b00
 @base=#<Task:0x00007fb0e0e93d40 id: nil, name: "do this last", description: nil, created_at: nil, updated_at: nil, completed: false>,
 @details={:prerequisite_tasks=>[{:error=>:invalid}, {:error=>:invalid}]},
 @messages={:prerequisite_tasks=>["is invalid"]}>

Оператор << также работает для добавления prerequisitesta = Task.create(name:"do this last", prerequisites:[Task.find(5), Task.find(6)] аналогично не работает.

Моя модель и контроллер (хотя я предполагаю, что контроллер на самом деле здесь не учитывается):

class Task < ApplicationRecord
  has_many :prerequisite_tasks, foreign_key: :do_second_id  
  has_many :prerequisites, through: :prerequisite_tasks, source: :do_first
end

class PrerequisiteTask < ApplicationRecord
  belongs_to :do_first, class_name: :Task
  belongs_to :do_second, class_name: :Task
end

class TasksController < ApplicationController
  def index
    render json: Task.all
  end

  def show
    task = Task.find(params[:id])
    render json: task
  end

  def create
    task = Task.create task_params
    render json: task, status: 201
  end
end

def task_params
  params.require(:task).permit :name, :description, :completed, prerequisite_ids: []
end

ОБНОВЛЕНИЕ

Я получил мои тесты, чтобы пройти с этим обходным путем:

  def create
    task = Task.create task_params.except(:prerequisite_ids)
    task.update prerequisite_ids: task_params[:prerequisite_ids]
    render json: task, status: 201
  end

Вставка в тесты показывает, что созданный объект И возвращенный json оба имеют правильный prerequisite_ids.Так что выглядит для работы.

Однако, когда я пытаюсь POST от Почтальона, он не принимает обновление prerequisite_ids:

Started POST "/tasks?task[name]=Post%20from%20Postman&task[description]=Testing%20value%20types&task[completed]=true&task[prerequisite_ids]=[5,6]" for ::1 at 2019-04-26 23:57:12 +0000
Processing by TasksController#create as */*
  Parameters: {"task"=>{"name"=>"Post from Postman", "description"=>"Testing value types", "completed"=>"true", "prerequisite_ids"=>"[5,6]"}}
Unpermitted parameter: :prerequisite_ids
   (0.6ms)  BEGIN
  ↳ app/controllers/tasks_controller.rb:12
  Task Create (1.2ms)  INSERT INTO "tasks" ("name", "description", "created_at", "updated_at", "completed") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["name", "Post from Postman"], ["description", "Testing value types"], ["created_at", "2019-04-26 23:57:12.373180"], ["updated_at", "2019-04-26 23:57:12.373180"], ["completed", true]]
  ↳ app/controllers/tasks_controller.rb:12
   (1.1ms)  COMMIT
  ↳ app/controllers/tasks_controller.rb:12
Unpermitted parameter: :prerequisite_ids
   (0.6ms)  BEGIN
  ↳ app/controllers/tasks_controller.rb:13
  Task Load (0.5ms)  SELECT "tasks".* FROM "tasks" WHERE 1=0
  ↳ app/controllers/tasks_controller.rb:13
  Task Load (1.0ms)  SELECT "tasks".* FROM "tasks" INNER JOIN "prerequisite_tasks" ON "tasks"."id" = "prerequisite_tasks"."do_first_id" WHERE "prerequisite_tasks"."do_second_id" = $1  [["do_second_id", 15]]
  ↳ app/controllers/tasks_controller.rb:13
   (0.2ms)  COMMIT
  ↳ app/controllers/tasks_controller.rb:13
[active_model_serializers] Rendered TaskSerializer with ActiveModelSerializers::Adapter::Attributes (1.58ms)
Completed 201 Created in 55ms (Views: 7.9ms | ActiveRecord: 5.1ms)

Возвращенноеобъект:

{
    "id": 16,
    "name": "Post from Postman",
    "description": "Testing value types",
    "completed": true,
    "prerequisite_ids": []
}

1 Ответ

1 голос
/ 27 апреля 2019

prerequisite_ids не является атрибутом модели, поэтому вы не можете передать его в метод create.

Вместо этого это вспомогательный метод, добавленный в класс при создании отношения с has_many :prerequisites.

Подробнее об этой функции вы можете прочитать в Руководстве по Rails, Методы, добавленные has_many , а также в документах ActiveRecord :: Associations :: ClassMethods .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...