【问题标题】:Allowing multiple records in category to submit to listing允许类别中的多个记录提交到列表
【发布时间】:2018-10-19 17:29:35
【问题描述】:

如果选择了多个,我希望将多个(一组...)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 输入它们。

新的列表控制器:

  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

【问题讨论】:

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


【解决方案1】:

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

当然,相同的属性有三个相同的下拉列表,它只会选择最后一个下拉列表的选定值并将其传递给params。 p>

您需要将其设置为一个下拉菜单并允许多项选择像这样

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

注意 :category_ids:multiple =&gt; true 的变化。 :category_ids 是一种方法 (collection_singular_ids),用于提供 多对多 关联,Rails 将在后台使用该关联为连接表创建条目 .

:multiple =&gt; true 允许您选择多个选项并将这些ids 作为数组传递。比如像这样category_ids: ["1","2","3"]

现在来到您的控制器代码,您不应该为类别构建列表,因为您的方法不同。将您的新方法更改为以下

def new
  @listing = Listing.new
end

也不需要@categories = Category.all,因为您在select 中明确调用Category.all

最后在listing_params 中将category_ids 列入白名单,就像这样

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) 从listings 表中删除category_id

4) 为listingscategories 生成HABTM 连接表,如下所示

rails generate migration CreateJoinTableCategoryListing category listing

现在保存列表后,后台的rails 将为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: [])

【讨论】:

  • 我应该如何以最佳方式定义我的类别。我目前正在使用 seed.rb 并以这种方式输入(这就是我使用 validates_uniqueness_of :category 的原因,所以我在添加新的时不会创建重复项)。
  • @uno 这取决于你想做什么?您是否要与类别一起创建列表,那么您应该使用accepts_nested_attributes_for 和fields_for。或者,如果您想为现有类别创建列表,请尝试我的方法。仅供参考,validates_uniqueness_of :category 无效
  • 我使用类别来搜索列表。所以我希望在创建列表时能够选择多个类别来与列表一起使用。和类别将被预先定义。虽然,管理员(而不是用户)将/应该能够添加新的类别,然后能够将类别添加到现有或新列表中。希望能解释一下。我不确定我这样做是否正确
  • 我在原始帖子中更新了我的代码。条目正在保存,但 categories_listings 表没有保存任何内容。是否需要通过某种方式设置我的表单才能输入?
  • 我收到一个错误:“参数数量错误(给定 0,预期为 1..2)”另外,我更新了我的 category.rb 假设您打算将我的 category.rb 模型更新为您想要的说?当这确实有效时,我担心如果只输入 1 个类别会怎样,因为我希望每个列表允许 1-5 个类别。还关心“多重 => true”,因为我也尝试使用复选框系统,但这也行不通
【解决方案2】:

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

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

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

【讨论】:

  • 对于“ validates_uniqueness_of :category ”,如果我没有这个,类别将在导入时继续从 seed.rb 复制类别。有没有更好的方法来创建类别,例如“CATEGORY = %w{ cat1 cat2 cat3 cat4 }”并这样称呼它?或者也许你知道的其他方法会更好?
  • 我将我的模型固定为.. category.rb 到 has_many :listings.. 和 listings.rb 到 belongs_to :category, required: false 这是正确的方式吗?
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多