嵌套表单不创建嵌套的记录。

时间:2015-12-23 10:07:39

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

您好我有2个型号Product和ProductSize。我在Product表单中创建了ProductSize。

问题是,它不能持久创建ProductSizes。您应该能够访问product.product_sizes并显示ProductSizes列表。

product.rb

class Product < ActiveRecord::Base
  acts_as_taggable

  belongs_to :user
  belongs_to :category

  has_many :product_sizes
  has_many :product_images, :dependent => :destroy

  validates :title, presence: true, length: { maximum: 30 }
  validates :description, presence: true, length: { maximum: 2000 }
  validates :category, :user, :price, presence: true

  accepts_nested_attributes_for :product_images, :product_sizes, allow_destroy: true
end

product_size.rb

class ProductSize < ActiveRecord::Base
  belongs_to :product
  belongs_to :size

  validates :quantity, presence: true
end

这是我的表格。它的工作方式是:用户可以上传图像,然后选择产品的类别。让我们说他们选择衬衫,然后所有衬衫尺寸的列表将下降像XS,小,中,大。然后,用户将他们拥有的数量放在他们拥有的尺寸上。比如13件XS衬衫和4件大衬衫。

<%= javascript_include_tag "custom" %>
<div class="container">
  <div class=“row”>
    <div class="col-md-6 col-md-offset-3">
      <div class="panel panel-primary">
        <div class="panel-body">
          <%= simple_nested_form_for @product do |f| %>
            <%= f.fields_for :product_images do |product_image| %>
              <% if product_image.object.new_record? %>
                <%= product_image.file_field(:product_image) %>
                <%= product_image.link_to_remove "Remove Image", data: { confirm: "Are you sure you want to delete this image?" } %>
              <% else %>
                <%= product_image.hidden_field :_destroy %>
              <% end %>
            <% end %>
            <p><%= f.link_to_add "Add a image", :product_images, :data => { :product_image => "#product_images" } %></p>
            <%= f.collection_select :category_id, @categories, :id, :name, include_blank: true, prompt: "Select One Category" %>

            <% @categories.each do |category| %>
              <div class='sizes_container' id ='sizes_container_for_<%= category.id %>'>
                <% category.sizes.each do |size| %>
                  <%= label_tag "product_form[sizes_by_id][#{size.id}]", size.title %>
                  <%= text_field_tag "product_sizes_attributes[sizes_quantity][#{size.id}]" %>
                <% end %>
              </div>
            <% end %>

            <%= f.input :title, label:"Title"%>
            <%= f.input :price, label:"Price"%>
            <%= f.input :description,label:"Description" %>
            <%= f.input :size_description, label:"Size Details"%>
            <%= f.input :shipping_description, label:"Shipping Details"%>
            <%= f.input :tag_list,label:"Tags - Seperate tags using comma ','. 5 tags allowed per product" %>
            <%= f.button :submit, "Create new product", class: "btn-lg btn-success" %>
          <% end %>
        </div>
      </div>
    </div>
  </div>
</div>

以下是我的参数在创建动作中的样子。

    36: def create
 => 37:   binding.pry
    38:   @product = Product.new product_params
    39:   @product.user_id = current_user.id
    40:   if @product.save
    41:     redirect_to @product
    42:     flash[:success] = "You have created a new product"
    43:   else
    44:     flash[:danger] = "Your product didn't save"
    45:     render "new"
    46:   end
    47: end

**[1] pry(#<ProductsController>)> product_params**
=> {"title"=>"test",
 "price"=>"3325",
 "description"=>"test",
 "tag_list"=>"test",
 "category_id"=>"3",
 "size_description"=>"test",
 "shipping_description"=>"test",
 "product_images_attributes"=>
  {"0"=>
    {"product_image"=>
      #<ActionDispatch::Http::UploadedFile:0x007f8cb786a010
       @content_type="image/jpeg",
       @headers="Content-Disposition: form-data; name=\"product[product_images_attributes][0][product_image]\"; filename=\"780069_black_l.jpg\"\r\nContent-Type: image/jpeg\r\n",
       @original_filename="780069_black_l.jpg",
       @tempfile=#<File:/var/folders/yx/znmx6qfj0c507bvkym6lvhxh0000gn/T/RackMultipart20151223-46388-p07o84.jpg>>,
     "_destroy"=>"false"},
   "1450863732810"=>
    {"product_image"=>
      #<ActionDispatch::Http::UploadedFile:0x007f8cb7869e08
       @content_type="image/jpeg",
       @headers="Content-Disposition: form-data; name=\"product[product_images_attributes][1450863732810][product_image]\"; filename=\"20090a.jpg\"\r\nContent-Type: image/jpeg\r\n",
       @original_filename="20090a.jpg",
       @tempfile=#<File:/var/folders/yx/znmx6qfj0c507bvkym6lvhxh0000gn/T/RackMultipart20151223-46388-n9mzf2.jpg>>,
     "_destroy"=>"false"}}}

[2] pry(#<ProductsController>)> params
=> {"utf8"=>"✓",
 "authenticity_token"=>"jfh6vsb1N1zhAIFyzer4liwuV+iHQ+P8pF6mZHUyF8IXNn6oXqnLDse84jnrP3BKI889CWigIDqVMJncxOYZ9Q==",
 "product"=>
  {"product_images_attributes"=>
    {"0"=>
      {"product_image"=>
        #<ActionDispatch::Http::UploadedFile:0x007f8cb786a010
         @content_type="image/jpeg",
         @headers="Content-Disposition: form-data; name=\"product[product_images_attributes][0][product_image]\"; filename=\"780069_black_l.jpg\"\r\nContent-Type: image/jpeg\r\n",
         @original_filename="780069_black_l.jpg",
         @tempfile=#<File:/var/folders/yx/znmx6qfj0c507bvkym6lvhxh0000gn/T/RackMultipart20151223-46388-p07o84.jpg>>,
       "_destroy"=>"false"},
     "1450863732810"=>
      {"product_image"=>
        #<ActionDispatch::Http::UploadedFile:0x007f8cb7869e08
         @content_type="image/jpeg",
         @headers="Content-Disposition: form-data; name=\"product[product_images_attributes][1450863732810][product_image]\"; filename=\"20090a.jpg\"\r\nContent-Type: image/jpeg\r\n",
         @original_filename="20090a.jpg",
         @tempfile=#<File:/var/folders/yx/znmx6qfj0c507bvkym6lvhxh0000gn/T/RackMultipart20151223-46388-n9mzf2.jpg>>,
       "_destroy"=>"false"}},
   "category_id"=>"3",
   "title"=>"test",
   "price"=>"3325",
   "description"=>"test",
   "size_description"=>"test",
   "shipping_description"=>"test",
   "tag_list"=>"test"},
 "product_sizes_attributes"=>{"sizes_quantity"=>{"1"=>"3", "2"=>"4", "3"=>""}},
 "commit"=>"Create new product",
 "controller"=>"products",
 "action"=>"create"}

[3] pry(#<ProductsController>)> params[:product_sizes_attributes]
=> {"sizes_quantity"=>{"1"=>"3", "2"=>"4", "3"=>""}}

2 个答案:

答案 0 :(得分:1)

您的表单看起来没有fields_for的{​​{1}}:

product_sizes

必须使用适当的控制器代码进行备份:

<%= simple_nested_form_for @product do |f| %>
   <%= f.fields_for :product_sizes do |product_size| %>
       <%= product_size.text_field .... %>
   <% end %>
<% end %>

这应该让它适合你。

答案 1 :(得分:0)

fields_for使用project_size。从@sizes获取总@categories并使用之前使用过的collection_select。您的project_size表单代码

<% @categories.each do |category| %>
   <div class='sizes_container' id ='sizes_container_for_<%= category.id %>'>
   <% category.sizes.each do |size| %>
     <%= label_tag "Size"product_form[sizes_by_id][#{size.id}]", size.title %>
     <%= text_field_tag "product_sizes_attributes[sizes_quantity][#{size.id}]" %>
   <% end %>
   </div>
<% end %>

将是

<% @sizes = Size.joins(:category).where('categories.id IN (?)', @categories.map(&:id)) %>

<%= f.fields_for :product_sizes do |product_size| %>
   <%= label_tag "Size" %>
   <%= product_size.collection_select :size_id, @sizes, :id, :title, include_blank: true, prompt: "Select One Size" %>
   <%= product_size.text_field :quantity %>
<% end %>

product_params将是

params.require(:product).permit(:title, :price, :description, :tag_list,:category_id, :size_description, :shipping_description, product_images_attributes: [:id, product_image: [] ], product_sizes_attributes: [:id, :size_id, :quantity])

我希望这会有所帮助。