Повторение полей формы и обновление до базы данных - PullRequest
0 голосов
/ 10 апреля 2020

любая помощь будет наиболее ценной, я довольно новичок в Rails.

У меня есть две модели: Список покупок и Продукт. Я хочу сохранить / обновить несколько товаров в списке покупок одновременно.

Предлагаемые изменения не обновляют модели. Я гуглил и отвечаю "attr_accessor" или find_or_create_by?

Попытка 1 - Существующий код

Ошибка

> unknown attribute 'products_attributes' for Product.
Request
Parameters:

{"_method"=>"patch",
 "authenticity_token"=>"3BgTQth38d5ykd3EHiuV1hkUqBZaTmedaJai3p9AR1N2bPlHraVANaxxe5lQYaVcWNoydA3Hb3ooMZxx15YnOQ==",
 "list"=>
  {"products_attributes"=>
    {"0"=>{"title"=>"ten", "id"=>"12"},
     "1"=>{"title"=>"two", "id"=>"13"},
     "2"=>{"title"=>"three", "id"=>"14"},
     "3"=>{"title"=>"four", "id"=>"15"},
     "4"=>{"title"=>"five", "id"=>"16"},
     "5"=>{"title"=>""},
     "6"=>{"title"=>""},
     "7"=>{"title"=>""},
     "8"=>{"title"=>""},
     "9"=>{"title"=>""},
     "10"=>{"title"=>""}}},
 "commit"=>"Save Products",
 "id"=>"7"}

Попытка 2 - ошибок нет страница перезагрузится, и ни одно из ожидаемых полей не будет обновлено. Серьезно, я гуглюсь и копирую и вставляю фрагменты кода в тщетной надежде разблокировать правильную комбинацию. Добавлено в режим продуктов

    class Product < ApplicationRecord
      attr_accessor :products_attributes
      belongs_to :list, optional: true
    end

<%= content_tag(:h1, 'Add Products To This List') %>
<%= form_for(@list) do |f| %>
  <%= f.fields_for :products do |pf| %>
    <%= pf.text_field :title %><br>
  <% end %>
  <p>
    <%= submit_tag "Save Products" %>
  </p>
<% end %>
<%= link_to "Back To List", lists_path %>

список контроллеров

    def update
        #render plain: params[:list].inspect
        @list = List.find(params[:id])
        if @list.products.update(params.require(:list).permit(:id, products_attributes: [:id, :title]))
            redirect_to list_path(@list)
        else
            render 'show'
        end

список моделей

    class List < ApplicationRecord
        has_many :products
        accepts_nested_attributes_for :products
    end

оригинал ничего не делать - модель продукта

    class Product < ApplicationRecord
      belongs_to :list, optional: true
    end

1 Ответ

0 голосов
/ 10 апреля 2020

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

class List < ApplicationRecord
  has_many :list_items
  has_many :products, through: :list_products
end

class ListItem < ApplicationRecord
  belongs_to :list
  belongs_to :product
end

class Product < ApplicationRecord
  has_many :list_items
  has_many :lists, through: :list_products
end

Это позволяет избежать создания огромного количества дубликатов в таблице продуктов и известен как нормализация .

Затем вы можете выбрать существующие продукты, просто используя команду select:

<%= form_for(@list) do |f| %>
  <%= f.label :product_ids %>
  <%= f.collection_select(:product_ids, Product.all, :name, :id) %>
  # ...
<% end %>

Обратите внимание, что это не имеет ничего общего с вложенными маршрутами или вложенными атрибутами. Это просто выбор, который использует установщик product_ids, созданный ассоциацией. Эта форма будет по-прежнему отправляться на /lists или /lists/:id

. Вы можете внести в белый список массив идентификаторов:

def list_params
  params.require(:list)
        .permit(:foo, :bar, product_ids: [])
end

Чтобы добавить создание / обновление / удаление группы вложенных записей в одна форма, которую вы можете использовать accepts_nested_attributes_for вместе с fields_for:

class List < ApplicationRecord
  has_many :list_items
  has_many :products, through: :list_products
  accepts_nested_attributes_for :products
end

<%= form_for(@list) do |f| %>
  <%= form.fields_for :products do |pf| %>
    <%= pf.label :title %><br>
    <%= pf.text_field :title %>
  <% end %>
  # ...
<% end %>

Конечно, fields_for ничего не покажет, если вы не создадите связь с записями. Вот где приходит тот l oop, который вы совершенно неуместны.

class ListsController < ApplicationController
  # ...
  def new
    @list = List.new
    5.times { @list.products.new } # seeds the form 
  end

  def edit
    @list = List.find(params[:id])
    5.times { @list.products.new } # seeds the form
  end
  # ...

  def update
    @list = List.find(params[:id])
    if @list.update(list_params)
      redirect_to @list
    else
      render :new
    end
  end

  private
  def list_params
    params.require(:list)
          .permit(
            :foo, :bar,
            product_ids: [],
            products_attrbutes: [ :title ]
          )
  end
end

Обязательное чтение:

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