【问题标题】:has_many through + check_box_tag not workinghas_many through + check_box_tag 不起作用
【发布时间】:2016-03-26 05:33:36
【问题描述】:

我有三个模型:ProductTypeProductAttributeProductTypeAttribute。 ProductType 和 ProductAttribute 是对象,ProductTypeAttribute 是一个连接(使用 has_many :through)。

当用户创建或更新ProductType时,他可以通过复选框选择ProductType中的ProductAttributes。 我的问题:

  • 在连接表 (ProductTypeAttribute) 中只创建了一条记录,没有参考选中了多少个复选框
  • 在连接表中只有“product_type_id”有值,“product_attribute_id”为NULL

感谢您的帮助!

我的 ProductType 模型:

class ProductType < ActiveRecord::Base

has_many :product_type_attributes, dependent: :destroy
has_many :product_attributes, through: :product_type_attributes 

end

我的 ProductAttribute 模型:

class ProductAttribute < ActiveRecord::Base
has_many :product_type_attributes, dependent: :destroy
has_many :product_types, through: :product_type_attributes  

end

我的 ProductTypeAttribute 模型:

class ProductTypeAttribute < ActiveRecord::Base
belongs_to :product_type
belongs_to :product_attribute

end

我的表格:

<%= form_for @product_type do |f| %>

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



  <p>
    <%= f.label "product type name" %><br>
    <%= f.text_field :type_name %>
  </p>

  <p>
    <%= f.label "description" %><br>
    <%= f.text_area :type_desc %>
  </p>

<% ProductAttribute.all.each do |attribute| %>
   <label>
      <%= check_box_tag 'attribute_ids[]', attribute.id, @product_type.product_attributes.include?(attribute) %>
      <%= label_tag :attribute_ids, attribute.name %>
   </label>
<% end %>

<p>
    <%= f.submit %>
  </p>
<% end %>

我的产品类型控制器

class ProductTypesController < ApplicationController
def index
        @product_types = ProductType.all
  end


  def show
        @product_type = ProductType.find(params[:id])
  end


    def new
     @product_type = ProductType.new
    end


    def edit
    @product_type = ProductType.find(params[:id])

  end


  def create
        @product_type = ProductType.new(product_type_params)      
        @product_type.product_type_attributes.build
        @product_type.save

        redirect_to @product_type
    end


  def update
    @product_type = ProductType.find(params[:id])

    @product_type.product_type_attributes.build

      if @product_type.update(product_type_params)

        redirect_to @product_type
      else
        render 'edit'
      end
  end


    def destroy
      @product_type = ProductType.find(params[:id])
      @product_type.destroy

      redirect_to product_types_path
end


  def product_type_params
        params.require(:product_type).permit(:type_desc, :type_name, {attribute_ids: []})
    end
end

【问题讨论】:

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


    【解决方案1】:

    您的代码看起来很混乱。

    在连接表(ProductTypeAttribute)中只创建了一条记录,没有参考检查了多少个复选框

    无论如何,这将是标准行为。

    在创建记录时,Rails 只会创建单个记录,除非您明确使用代码循环通过多个复选框并为每个复选框创建记录。

    --

    说实话,我认为你不必要地让你的人际关系复杂化了。

    您可以在product_types 关联中使用has_and_belongs_to_many

    #app/models/product.rb
    class Product < ActiveRecord::Base
       has_and_belongs_to_many :types, class_name: "Product::Type"
    end
    
    #app/models/product/type.rb
    class Product::Type < ActiveRecord::Base
       has_and_belongs_to_many :products, class_name: "Product"
    end
    

    这将允许您为每个产品创建任意数量的types (collection check boxes):

    #app/views/products/edit.html.erb
    <%= form_for @product do |f| %>
       <%= f.check_box :type_ids, Product::Type.all, :id, :name %>
       <%= f.submit %>
    <% end %>
    
    #app/controllers/products_controller.rb
    class ProductsController < ApplicationController
       def update
          @product = Product.new product_params
          @product.save
       end
    
       private
    
       def product_params
          params.require(:product).permit(:type_ids)
       end
    end
    

    如果您想为Product::Type 模型添加属性,您可以使用:

    #app/models/product/attribute.rb
    class Product::Attribute < ActiveRecord::Base
       belongs_to :type, class_name: "Product::Type"
    end 
    

    ... 并没有真正回答您的问题,但我认为应该可以解决您的大部分基础架构问题。


    专业提示 - 如果您使用的是“嵌套”在另一个模型下的模型,您应该将它们superclass 传递给它们的“父”模型:

    -- models
     -- product.rb
     -- product
      -- type.rb
      -- attribute.rb
      -- type_attribute.rb
    

    这将导致以下结果:

    #app/models/product.rb
    class Product < ActiveRecord::Base
       has_many :types, class_name: "Product::Type"
    end
    
    #app/models/product/type.rb
    class Product::Type < ActiveRecord::Base
       belongs_to :product
    end
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-04
    • 2016-01-20
    • 1970-01-01
    • 2011-10-06
    • 1970-01-01
    相关资源
    最近更新 更多