允许类别中的多个记录提交列表

时间:2018-10-17 23:44:57

标签: ruby-on-rails ruby ruby-on-rails-4

如果选择多个列表,我希望将多个(数组...)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中定义了类别,然后在需要添加它们时使用db:seed进行输入。

新版上市控制器:

  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 :(得分:0)

您的数据关系似乎不正确。看看:

  • Category模型验证category的唯一性。但是类别表中没有字段类别。似乎应该改用名称。
  • Listing模型has and belongs to many categories。对于Rails而言,这意味着这两个表是通过第三个表categories_listings连接的,该表包含category_idlisting_id。但是您的数据库架构有所不同-表category_id属于listings表,该表匹配[Category模型has many listings]的关联。有矛盾。

我将数据模型视为整个应用程序的基础。拥有正确的数据模型,为控制器和视图编写代码变得透明而明显。首先修复您的数据模型,然后使用nested attributes保存关联的模型。

答案 1 :(得分:0)

  

当我使用第一个“ form.select:category_id”时,会弹出3滴   下来,只有最后选择的下拉菜单会保存。如果我选择3个单独的   分类,只有最后选择的一个会保存。我希望能够   为每个列表选择多个类别。

当然,您要为 same属性使用三个相同的下拉列表,它只会选择上一个下拉列表的选定值并将其传递给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_forfields_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)如下生成listingscategories的HABTM连接表

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: [])

答案 2 :(得分:0)

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 %>