Как я могу создать объект модели с глубоко вложенными ассоциациями в Rails, используя только мой метод белого списка params? - PullRequest
0 голосов
/ 19 ноября 2018

Чтобы повторить этот вопрос, моя базовая модель: project:

class Project < ApplicationRecord
  has_many :tones, as: :analyzable
  has_many :sentences
  accepts_nested_attributes_for :tones, :sentences
end

И у меня есть две другие модели:

class Sentence < ApplicationRecord
  belongs_to :project
  has_many :tones, as: :analyzable
  accepts_nested_attributes_for :tones
end

class Tone < ApplicationRecord
  belongs_to :analyzable, polymorphic: true
end

В моем ProjectsController я хочу иметь одно действие create, которое просто принимает параметры из белого списка и создает проект со всеми соответствующими ассоциациями. Мой метод project_params выглядит так:

private
  def project_params
    params.permit(:text, :title, :img, sentences_attributes: [:id, :text, tones_attributes: [:score, :tone_name]], tones_attributes: [:id, :score, :tone_name])
  end

Но если я попробую что-то вроде:

project = Project.create(project_params)

Я получу ошибку, подобную приведенной ниже:

| ActiveRecord::AssociationTypeMismatch (Sentence(#70119358770360) expected, got {"text"=>"extremely disappointed with the level of service with Virgin Media.", "tones"=>[{"score"=>0.64031, "tone_name"=>"Sadness"}, {"score"=>0.618451, "tone_name"=>"Confident
"}]} which is an instance of ActiveSupport::HashWithIndifferentAccess(#70119356172580)):

Я закончил тем, что написал это для своего действия создания, которое выполняет работу, но чувствует себя довольно неуклюжим:

    project = Project.create({text: params[:text], title: params[:title], 
    img: params[:img]})
    params[:sentences].each do |sent|
      sentence = project.sentences.create({text: sent["text"]})
      sent["tones"].each do |tone|
        sentence.tones.create({score: tone["score"], tone_name: tone["tone_name"]})
      end
    end

    params[:tones].each do |tone|
      project.tones.create({score: tone["score"], tone_name: tone["tone_name"]})
    end

Есть ли лучший способ справиться с подобной ситуацией, чем тот, что я описал выше, когда кто-то пытается создать объект из вложенных параметров, имеющих несколько уровней ассоциации?

...