错误:表单中有很多关系,更新时有重复数据

时间:2016-09-17 23:07:01

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

我正在做电子商务。 我的产品有很多产品选择,同时它们只有一个变体。 我尝试使视图创建产品可以选择添加块,其中显示模型的字段以及与之关联的变体的更改。问题是,例如,当我创建一个有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

产品参数

def product_params
    params.require(:product).permit(:name, :description, :state, :shippingInside, :vendor_id, :category_id, :priceComparison, :image1, :price, offer_attributes: [:status], options_products_attributes: [:price, :stock, variant_attributes: [:tipoVariant, :controlStock, :image]])

在应用程序助手中添加关联功能

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 of Product

= 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'

1 个答案:

答案 0 :(得分:0)

在product_params中,您应指定options_products_attributes的id。如果没有id,属性将被新添加到产品模型中。 所以,试试吧     ... options_products_attributes:[:id,price,:stock,variant_attributes:[:id,:tipoVariant,...