【问题标题】:Rails 5: Many-to-Many Relationship Not WorkingRails 5:多对多关系不起作用
【发布时间】:2018-01-13 12:15:35
【问题描述】:

我正在尝试在 Rails 5 项目中创建多对多表关系。

一个Shop 可以有多个Categories,它们在Shop_Categories 表中被索引。

不过,我似乎错过了一个关键步骤。当我提交我的 Shop 表单时,我收到了软错误:"Unpermitted parameter: :shop_category"

我可以在 Rails 服务器日志中看到我的 shop_category 参数已成功发送,但 Shop_Categories 表根本没有更新。

我遗漏了什么,我可以更改什么以便在Shop 视图表单上按保存更新Shop_Categories 表?

这是我的代码。 店铺模式

class Shop < ApplicationRecord
    belongs_to :type

    has_many :shop_categories
    has_many :categories, through: :shop_categories

    accepts_nested_attributes_for :shop_categories

    enum status: [:open, :closed, :opening_soon, :closing_soon]
end

Shop_Category 模型

class ShopCategory < ApplicationRecord
    belongs_to :shop
    belongs_to :category
end

类别模型

class Category < ApplicationRecord
    has_many :subcategories, dependent: :destroy

    has_many :shop_categories
    has_many :shops, through: :shop_categories
end

店长(摘录)

def new
    @shop = Shop.new
    @shop.shop_categories.build
end

def create
    @shop = Shop.new(shop_params)

    @shop.open_date = params[:shop][:open_date]+"-01"
    @shop.close_date = params[:shop][:close_date]+"-01"

    if @shop.save
        redirect_to @shop
    else
        render 'new'
    end
end

def update
    @shop = Shop.find(params[:id])

    if @shop.update(shop_params)
        redirect_to @shop
    else
        render 'edit'
    end
end

private
    def shop_params

        params[:shop][:open_date] = params[:shop][:open_date]+"-01"
        params[:shop][:close_date] = params[:shop][:close_date]+"-01"

        params.require(:shop).permit(:shop_name, :type_id, :status,
          :phone_number, :mobile_number, :email_address, :open_date,
          :close_date, shop_categories_attributes: [ :shop_id, :category_id] )
    end

商店表单视图(摘录)

<p>
    <%= form.label :shop_name %><br>
    <%= form.text_field :shop_name %>
</p>

<%= form.fields_for :shop_category do |category_fields| %>
    <p>
        <%= category_fields.label :category %><br />
        <%= category_fields.collection_select(:category_id, Category.all, :id, :category_name, include_blank: true) %>
    </p> 
<% end %>

<p>
    <%= form.submit %>
</p>

最后,数据库架构

create_table "categories", force: :cascade do |t|
    t.string "category_name"
    t.text "category_description"
    t.string "visible_category"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
end

create_table "shop_categories", force: :cascade do |t|
    t.string "visible_category_override"
    t.integer "shop_id"
    t.integer "category_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["category_id"], name: "index_shop_categories_on_category_id"
    t.index ["shop_id"], name: "index_shop_categories_on_shop_id"
end

create_table "shops", force: :cascade do |t|
    t.string "shop_name"
    t.integer "status"
    t.integer "sale"
    t.string "phone_number"
    t.string "mobile_number"
    t.string "email_address"
    t.date "open_date"
    t.date "close_date"
    t.integer "type_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["type_id"], name: "index_shops_on_type_id"
end  

任何建议将不胜感激。我就是不知道我错过了哪一块拼图!

更新:包括开发日志和完整的商店表单。

开发日志

Started PATCH "/shops/1" for 127.0.0.1 at 2018-01-14 11:08:39 +0000
Processing by ShopsController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"2qydDj9JovMrg9VT6Lo5xbcNSHl5MH0ylmq3IMMX4iRTAVSgK6JlXWpG+CyuwQK6svZJn9wtnEnZANUlOZYzXA==",
    "shop"=>{"shop_name"=>"test", "type_id"=>"1",
    "shop_categories"=>{"category_id"=>"1"}, "subcategory_id"=>"", 
    "status"=>"open", "phone_number"=>"123", "mobile_number"=>"13212", 
    "email_address"=>"hello@test.com", "open_date"=>"2017-12",
    "close_date"=>"2017-12"}, "commit"=>"Update Shop", "id"=>"1"}
  Shop Load (0.5ms)  SELECT  "shops".* FROM "shops" WHERE "shops"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
Unpermitted parameters: :shop_categories, :subcategory_id
   (0.1ms)  begin transaction
  Type Load (0.2ms)  SELECT  "types".* FROM "types" WHERE "types"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   (0.1ms)  commit transaction
Redirected to http://localhost:3000/shops/1
Completed 302 Found in 10ms (ActiveRecord: 0.9ms)

完整视图/shops/_form.html.erb 文件

<%= form_with model: @shop, local: true do |form| %>

    <% if @shop.errors.any? %>
        <div id="error_explanation">
            <h2>
                <%= pluralize(@shop.errors.count, "error") %> prohibited
                this shop from being saved:
            </h2>
            <ul>
                <% @shop.errors.full_messages.each do |msg| %>
                    <li><%= msg %></li>
                <% end %>
            </ul>
        </div>
    <% end %>

    <p>
        <%= form.label :shop_name %><br>
        <%= form.text_field :shop_name %>
    </p>

    <p>
        <%= form.label :type %><br />
        <%= form.collection_select(:type_id, Type.all, :id, :type_name) %>
    </p> 

    <%= form.fields_for :shop_categories do |category_fields| %>
        <p>
            <%= category_fields.label :category %><br />
            <%= category_fields.collection_select(:category_id, Category.all, :id, :category_name, include_blank: true) %>
        </p> 
    <% end %>

    <p>
        <%= form.label :subcategory %><br />
        <%= form.grouped_collection_select :subcategory_id, Category.all, :subcategories, :category_name, :id, :visible_subcategory, include_blank: true %>
    </p> 
    <p>
        <%= form.label :status %><br />
        <%= form.select :status, Shop.statuses.keys %> 
    </p>

    <p>
        <%= form.label :phone_number %><br>
        <%= form.telephone_field :phone_number %>
    </p>

    <p>
        <%= form.label :mobile_number %><br>
        <%= form.telephone_field :mobile_number %>
    </p>

    <p>
        <%= form.label :email_address %><br>
        <%= form.email_field :email_address %>
    </p>

    <p>
        <%= form.label :open_date %><br>
        <%= form.month_field :open_date %>
    </p>

    <p>
        <%= form.label :close_date %><br>
        <%= form.month_field :close_date %>
    </p>

    <p>
        <%= form.submit %>
    </p>

<% end %>

【问题讨论】:

    标签: ruby-on-rails many-to-many ruby-on-rails-5 nested-forms


    【解决方案1】:

    应该是:shop_categories,而不是:shop_category

    <%= f.fields_for :shop_categories do |category_f| %>
      ...
    <% end %>
    

    您在 Shop_Category 模型部分也有点迷失我。实际的类名不同(ShopSubcategory),它属于_属于一个子类别?这也可能会导致一些错误。我猜你的意思是ShopCategoryjoin 模型和belongs_to :category

    更新

    同时确保在创建新表单时构建您的嵌套资源:

    #shop_controller
    
    def new
      @shop = Shop.new
      @shop.shop_categories.build
      ...
    end
    

    【讨论】:

    • 啊,对不起。我也有一个子类别表,但并不是要将模型复制到这篇文章中。为了清楚起见,我已经更新了原始版本。
    • 好的,我刚试过&lt;%= form.fields_for :shop_categories do |category_fields| %&gt;,但我仍然收到错误Unpermitted parameters: :shop_categories
    • 是在您尝试创建新商店还是编辑现有商店时?您可能还想继续学习本教程:railscasts.com/episodes/196-nested-model-form-part-1。您可能会发现在此过程中遗漏了一些基本内容,并且未包含在您的代码或我的建议中。
    • 好消息。那个 rails cast 和清理我的数据库帮助解决了这个问题。谢谢!
    • 有时当事情看起来太混乱时,您只需退后一步(或后退很多步)并重试。很高兴你明白了这一点!祝你好运!
    猜你喜欢
    • 2019-03-02
    • 2021-12-08
    • 1970-01-01
    • 2017-07-18
    • 1970-01-01
    • 1970-01-01
    • 2017-01-18
    • 1970-01-01
    相关资源
    最近更新 更多