2016-09-17 16 views
0

我在做电子商务。 我有产品有许多选择的产品,同时他们只有一个变种。 我尝试使视图创建产品可以选择添加一个块,其中显示模型的字段以及与其关联的变体的更改。问题是,例如,当我创建一个包含5个选项的产品时,当我将其更新为10时,如果我再次更新它,则会有20个选项。我无法找到问题,他们为什么重复。我将下面的代码留下。产品,期权产品和变异错误:表单中有很多关系,更新时有重复数据

create_table "options_products", force: :cascade do |t| 
    t.integer "product_id" 
    t.float "price" 
    t.integer "stock" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
end 

create_table "products", force: :cascade do |t| 
    t.string "name",    default: "", null: false 
    t.text  "description" 
    t.integer "category_id" 
    t.integer "vendor_id" 
    t.string "state",       null: false 
    t.boolean "shippingInside",     null: false 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    t.integer "priceComparison" 
    t.string "image1_file_name" 
    t.string "image1_content_type" 
    t.integer "image1_file_size" 
    t.datetime "image1_updated_at" 
    t.float "price" 
end 

create_table "variants", force: :cascade do |t| 
    t.string "tipoVariant" 
    t.integer "options_product_id" 
    t.datetime "created_at",   null: false 
    t.datetime "updated_at",   null: false 
    t.boolean "controlStock" 
    t.string "image_file_name" 
    t.string "image_content_type" 
    t.integer "image_file_size" 
    t.datetime "image_updated_at" 
end 

的脚本添加和删除字段

$(document).on 'ready page:load', -> 
    $('form').on 'click', '.remove_field', (event) -> 
    $(this).prev('input[type=hidden]').val('1') 
    $(this).closest('fieldset').hide() 
    event.preventDefault() 

$('form').on 'click', '.add_field', (event) -> 
    time = new Date().getTime() 
    regular_expression = new RegExp($(this).data('id'), 'g') 
    $(this).before($(this).data('fields').replace(regular_expression,time)) 
    event.preventDefault() 

产品创建和更新

def create 
    @product = Product.new(product_params) 

    respond_to do |format| 
     if @product.save 
      format.html { redirect_to @product} 
      format.json { render :show, status: :created, location: @product } 
     else 
      format.html { render :new } 
      format.json { render json: @product.errors, status: :unprocessable_entity } 
     end 
    end 
end 

def update 
    respond_to do |format| 
     if @product.update(product_params) 
      format.html { redirect_to @product} 
      format.json { render :show, status: :ok, location: @product } 
     else 
      format.html { render :edit } 
      format.json { render json: @product.errors, status: :unprocessable_entity } 
     end 
    end 
end 

产品PARAMS

模式在应用助手

功能添加关联

def link_to_add_association(name, field, association) 
    new_object = field.object.send(association).klass.new 
    new_object_id = new_object.object_id 
    fields = field.fields_for(association, new_object, child_index: new_object_id) do |builder| 
     new_object.build_variant 
     render(association.to_s.singularize + '_field', f: builder) 
    end 
    link_to(name, '#', class: 'add_field', data: { id: new_object_id, fields: fields.gsub("\n", "") }) 
end 

产品型号

class Product < ActiveRecord::Base 
    #relations 
    belongs_to :category 
    belongs_to :vendor 
    has_one :offer, :dependent => :destroy 
    has_many :options_products, :dependent => :destroy 

    #accepts 
    accepts_nested_attributes_for :offer, allow_destroy: true 
    accepts_nested_attributes_for :options_products, allow_destroy: true 

    #validations 
    validates :name, presence:true 
    validates :name, uniqueness:true 
    validates :state, presence:true 
    validates :category_id, presence:true 
    validates :vendor_id, presence:true 

    has_attached_file :image1, styles: {medium: "300x300>", thumb: "150x150#" } 
    validates_attachment_content_type :image1, content_type: /\Aimage\/.*\z/ 
end 

期权产品型号

class OptionsProduct < ActiveRecord::Base 
    belongs_to :product 
    has_one :variant, :dependent => :destroy 

    accepts_nested_attributes_for :variant, allow_destroy: true 
end 

派生模型

class Variant < ActiveRecord::Base 
    belongs_to :options_product 
    has_attached_file :image, 
        styles: {medium: "300x300>", thumb: "150x150#" } 
    validates_attachment_content_type :image, 
            content_type: /\Aimage\/.*\z/ 
end 

_form产品的

= form_for @product, html: { multipart: true } do |f| 
    .row 
    .form-group.col-lg-6 
     .field 
     = f.file_field :image1 

    .row 
    .form-group.col-lg-6 
     .field 
     = f.text_field :name, :placeholder => 'Nombre', :class => 'form-control input-border-left' 

    .row 
    .form-group.col-lg-6 
     .field 
     = f.text_area :description, :placeholder => 'Descripcion', :class => 'form-control input-border-left' 

    .row 
    .form-group.col-lg-6 
     .field 
     = f.number_field :price, :placeholder => 'Precio a mostrar', :class => 'form-control input-border-left' 

    .row 
    .form-group.col-lg-6 
     .field 
     = f.label :Estado 
     %br/ 
     = f.select :state, options_for_select(['Disponible', 'No disponible']) 

    .row 
    .form-group.col-lg-6 
     .field 
     = f.label :Envio 
     %br/ 
     = f.check_box :shippingInside 

    .row 
    .form-group.col-lg-6 
     .field 
     = f.text_field :priceComparison, :placeholder => 'Precio anterior', :class => 'form-control input-border-left' 

    .row 
    .form-group.col-lg-6 
     .field 
     = f.label :vendor_id 
     %br/ 
     = f.select :vendor_id, Vendor.all.collect { |vendor| [vendor.name, vendor.id] } 

    .row 
    .form-group.col-lg-6 
     .field 
     = f.label :category_id 
     %br/ 
     = f.select :category_id, Category.all.collect { |category| [category.name, category.id] } 

    = f.fields_for :offer, @product.build_offer do |o| 
    = o.label :Oferta 
    %br/ 
    = o.check_box :status 
    %br/ 
    .row 
    = f.fields_for :options_products do |op| 
    = render 'options_product_field', f: op 
    = link_to_add_association 'Agregar variante', f, :options_products 
    %br/ 
    .actions 
    = f.submit "Enviar", :class => 'button btn btn-primary bold' 

options_product_field文件

%fieldset 
    .row 
    .form-group.col-lg-6 
     .field 
     = f.text_field :price, :placeholder => 'Precio', :class => 'form-control input-border-left' 
    .row 
    .form-group.col-lg-6 
     .field 
     = f.text_field :stock, :placeholder => 'Stock', :class => 'form-control input-border-left' 

    = f.fields_for :variant do |v| 
    .row 
     .form-group.col-lg-6 
     .field 
      = v.text_field :tipoVariant, :placeholder => 'Tipo de variante', :class => 'form-control input-border-left' 
    .row 
     .form-group.col-lg-6 
     .field 
      = v.label :ControlarStock 
      %br/ 
      = v.check_box :controlStock 
    .row 
     .form-group.col-lg-6 
     .field 
      = v.label :ImagenDeVariante 
      %br/ 
      = v.file_field :image 
    = f.hidden_field :_destroy 
    = link_to 'Remover variante', '#', class: 'remove_field' 

回答

0

在product_params,你应该指定options_products_attributes的ID。没有id,属性将被新添加到产品模型中。 所以,尽量 ... options_products_attributes:[:ID,价格:股票,variant_attributes:[:ID,:tipoVariant,...

+0

所以,当我有一个模型的has_many我用nested_attributes,我需要把ID放在参数中? –

+0

是的,当你想只更新nested_attributes的记录。如果要将nested_attributes的记录添加到父模型,请删除参数中的ID。 – YTorii