Rails принимает_nested_attributes_for с принадлежащим.Почему я не могу установить идентификатор? - PullRequest
0 голосов
/ 29 ноября 2018

Я использую Rails 5.1.6 и у меня проблемы с accepts_nested_attributes_for.

У меня две модели

class Material < ApplicationRecord
  belongs_to :rubric, optional: true
  accepts_nested_attributes_for :rubric
end

class Rubric < ApplicationRecord
  has_many :materials, dependent: :nullify
end

Я пытаюсь установить идентификатор рубрики для нового элемента с помощью rubric_attributes.

describe 'create material' do
  it 'should set rubric: :id' do
    # prepare
    item = FactoryBot.build(:material)
    rubric = FactoryBot.create(:rubric)

    # action
    item.assign_attributes(
      rubric_attributes: {
        id: rubric.id
      }
    )

    # check
    expect(item.valid?).to eq(true)
    expect(item.save).to eq(true)
    expect(item.rubric_id).to eq(rubric.id)
  end
end

Но у меня есть ошибка:

 Failure/Error:
   item.assign_attributes(
     rubric_attributes: {
       id: rubric.id
     }
   )

 ActiveRecord::RecordNotFound:
   Couldn't find Rubric with ID=1 for Material with ID=1

И у меня та же ошибка с обновлением материала.

Это предсказуемое поведение acceptpts_nested_attributes_for, и я не могуиспользовать rubric_attributes для установки существующего идентификатора рубрики?

Ответы [ 2 ]

0 голосов
/ 29 ноября 2018

Во-первых, вам, скорее всего, не нужно accepts_nested_attributes_for.

Если вы хотите, чтобы пользователь мог выбирать записи с помощью выбора, вам на самом деле не нужно ничего делать, кроме как создатьвыберите и внесите в белый список атрибут material_id:

<%= form_for(@material) do |f| %>
  <div class="field">
    <%= f.label :rubic_id %>
    <%= f.collection_select :rubic_id, Rubic.all :id, :name %>
  </div>
  <%= f.submit %>
<% end %>

При выборе будет создан массив в параметрах.

class MaterialsController
  # POST /materials
  def create
    @material = Material.new(material_params)
    if @material.save
      redirect_to @material
    else
      render :new
    end
  end

  private

    def material_params
      params.require(:material)
            .permit(:foo, :bar, material_ids: [])
    end
end

accepts_nested_attributes_for действительно предназначен для случая, когда вам нужно создавать / редактировать вложенные ресурсы в одном запросе.Единственная причина, по которой вы бы использовали его здесь:

  1. Пользователь должен иметь возможность создавать материал в той же форме.
  2. У вас есть таблица соединения с дополнительными атрибутами (например, количествонапример), который вы хотите, чтобы пользователь мог установить.

Вы все еще можете сделать 1. вместе с выбором выше, но вы не можете использовать accepts_nested_attributes_for для установки простого belongs_to ассоциация.И вам не хотелось бы использовать ракету, чтобы бить гвоздем.

0 голосов
/ 29 ноября 2018

Документы скажем:

Для каждого хеша, у которого нет ключа id, будет создана новая запись, если хеш также не содержит ключ _destroy, который оцениваетв true.

Предполагается, что если вы передадите id во вложенных атрибутах, он будет считаться существующей записью, которая должна быть обновлена.

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