Разрешение нескольких записей в категории для отправки в список - PullRequest
0 голосов
/ 18 октября 2018

Я хочу, чтобы в каждом листинге было сохранено несколько (массив ...) category_id, если выбрано более одного.Ниже описано, как все настроено, включая то, как категории работают вместе со списками.

Модель категории:

class Category < ApplicationRecord
  validates_uniqueness_of :category
  has_many :listings

Модель списка:

  has_and_belongs_to_many :categories, required: false
  attr_accessor :new_category_name
  before_save :create_category_from_name

  # has_many :categories

Схема (для категорийи списки):

  create_table "categories", force: :cascade do |t|
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "listings", force: :cascade do |t|
    t.string "name"
    t.text "description"
    t.decimal "price"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "image"
    t.integer "user_id"
    t.integer "category_id"
    t.index ["category_id"], name: "index_listings_on_category_id"
  end

Затем у меня есть категории, определенные в seed.rb, а затем rails db: seed для ввода их, когда мне нужно их добавить.

Listing Controller for New:

  def new
    @listing = Listing.new
    @categories = Category.all

    3.times do
      @listing.categories.build
    end


  end

Представления формы для создания листинга (вкратце):

<%= form_with(model: listing, local: true) do |form| %>

<%= form.label "Choose Up to 3 Categories (1 required)"%>

  <div class="space">
    <%= form.select :category_id, options_from_collection_for_select(Category.all, :id, :name), :prompt => "Select a Category" %>
    <%= form.select :category_id, options_from_collection_for_select(Category.all, :id, :name), :prompt => "Select a Category" %>
    <%= form.select :category_id, options_from_collection_for_select(Category.all, :id, :name), :prompt => "Select a Category" %>
  </div>

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  <%= form.label "Choose Up to 3 Categories (1 required)"%>

    <div class="space">
  <% form.fields_for :category_id do |c| %>
    <%= c.select :category_id, options_from_collection_for_select(Category.all, :id, :name), :prompt => "Select a Category" %>
    <% end %>
  </div>

  <% form.fields_for :category_id do |c| %>
    <%= c.text_field :category_id %>
    <% end %>

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Между "~~~~~~~~~~~~~~~~~"~~~~ "мои попытки проверить это.Они даже не отображаются в форме, хотя я не знаю почему.

Когда я использую первый «form.select: category_id», который вызывает 3 выпадающих списка, только последнее выбранное падениевниз спасает.Если я выберу 3 отдельные категории, будет сохранена только последняя выбранная категория.Я хочу иметь возможность выбирать несколько категорий для каждого списка.

Как разрешить сохранение нескольких категорий при создании нового списка?Будь то выпадающий список, чекбоксы и т. Д. Просто нужно иметь возможность нескольких сохранений в одном списке, если пользователь выбрал более одного.

ОБНОВЛЕНИЕ:

Схема:

create_table "categories", force: :cascade do |t|
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "categories_listings", id: false, force: :cascade do |t|
    t.integer "category_id", null: false
    t.integer "listing_id", null: false
  end

Вид формы:

<%= form.select :category_ids, options_from_collection_for_select(Category.all, :id, :name), :prompt => "Select a Category", :multiple => true %>

Параметры управления:

params.require(:listing).permit(:attr1, :name, :description, :price, :image, :category_id, category_ids: [])

Модели:

    Category
      has_and_belongs_to_many :listings


Listing

belongs_to :category, required: false
  belongs_to :categories_listings, required: false

Ответы [ 3 ]

0 голосов
/ 18 октября 2018

Когда я использую первый «form.select: category_id», который вызывает 3 раскрывающихся списка, сохраняется только последний выбранный раскрывающийся список.Если я выберу 3 отдельные категории, будет сохранена только последняя выбранная категория.Я хочу иметь возможность выбрать несколько категорий для каждого списка.

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

. Вам нужно установить его как один выпадающий список и разрешить множественный выбор на нем, например, так

<%= form.select :category_ids, options_from_collection_for_select(Category.all, :id, :name), :prompt => "Select a Category", :multiple => true %>

Обратите внимание на изменения :category_ids и :multiple => true.:category_ids - это метод (collection_singular_ids), который отправляет для связей многие-ко-многим , которые будут использоваться Rails под капотом для создания записей для объединенногоТаблица .

:multiple => true позволяет выбрать более одной опции и передать эти ids в виде массива.Например, вот так: category_ids: ["1","2","3"]

Теперь, перейдя к коду вашего контроллера, вы не должны создавать списки для категорий, поскольку ваш подход отличается.Измените свой новый метод на

def new
  @listing = Listing.new
end

Также не обязательно иметь @categories = Category.all, поскольку вы явно вызываете Category.all в select

И, наконец, белый список category_idsв listing_params вот так

params.require(:listing).permit(:attr1, .... category_ids: [])

Между "~~~~~~~~~~~~~~~~~~~~~" мои попытки его протестировать,Они даже не отображаются в форме, хотя я не знаю, почему.

Ну, вы запутались с accepts_nested_attributes_for, а также с fields_for.Читайте дальше!

Примечание:

Также, как упомянуто @ IIya Konyukhov , ваша схема выглядит иначе для ассоциации HABTM ,Вы должны изменить свою схему так, чтобы она соответствовала потребностям вашего подхода к работе.

Обновление # 1

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

Вышеупомянутый подход должен соответствовать вашим потребностям, но в вашем коде нужно сделать больше настроек, чтобы он работал.

1) Ассоциации в Category модели имеют недостатки.Вам нужно изменить has_many :listings на has_and_belongs_to_many :listings

2) Удалить validates_uniqueness_of :category из модели категории, так как она недопустима.

3) Удалить category_id из listings таблицы

4) Создайте объединенную таблицу HABTM для listings и categories, как показано ниже

rails generate migration CreateJoinTableCategoryListing category listing

Теперь после сохранения списка рельсы под колпаком будут создавать записи для categories_listingsчто будет правильным для вышеупомянутого подхода.

Хотя новые могут / должны быть добавлены администраторами (а не пользователями), чтобы затем иметь возможность добавлять категорию к существующим илиновый листинг

Это также можно сделать тем же способом, что и выше, для создания нового листинга с существующими категориями.И просто отредактируйте форму редактирования списка, чтобы добавить существующую категорию для этого списка.Вам просто нужно убедиться, что эти маршруты отличаются и доступны только администраторам.

Обновление № 2:

Вам необходимо удалить свои текущие ассоциации в Listing смоделируйте и добавьте в него следующий код.

#listing.rb
has_and_belongs_to_many :categories

А также удалите category_id из списка параметров.Просто держи category_ids: []

params.require(:listing).permit(:attr1, :name, :description, :price, :image, category_ids: [])
0 голосов
/ 18 октября 2018

has_and_belongs_to_many просто поддерживает массив вложенных параметров, вы должны разрешить параметры, подобные этому params.require(:listing).permit(:attr, ..., category_ids: []), затем изменить в форме с помощью этого кода

<%= form.select :category_ids, options_from_collection_for_select(Category.all, :id, :name), :prompt => "Select Categories", multiple: true %>
0 голосов
/ 18 октября 2018

Ваше отношение к данным, похоже, неверно.Взгляните:

  • Category модель подтверждает уникальность category.Но в таблице категорий нет категории полей.Кажется, вместо этого следует использовать имя.
  • Listing модель has and belongs to many categories.Для Rails это означает, что эти 2 таблицы связаны через 3-ю таблицу categories_listings, которая содержит category_id и listing_id.Но ваша схема базы данных отличается - в ваших таблицах category_id принадлежит таблице listings, что соответствует ассоциации [Category модель has many listings].Здесь есть противоречие.

Я бы рассматривал модель данных как основу для всего приложения.При правильной модели данных написание кода для контроллеров и представлений становится прозрачным и очевидным.Сначала исправьте модель данных и используйте вложенные атрибуты для сохранения связанных моделей.

...