首页 \ 问答 \ 错误:表单中有很多关系,更新时有重复数据(Error: has-many relationship in form, duplicate data when update)

错误:表单中有很多关系,更新时有重复数据(Error: has-many relationship in form, duplicate data when update)

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

I am doing an e-commerce. I have products which have many options of products and at the same time they only have one variant. I try to make the view to create the product have the option of add a block where appears the fields of the model and the changes of the variant which is associated to it. The problem is, for example, when i create a product with 5 options, when i update it increases to 10, and if i update it again, there will be 20. I can't find the problem why they are duplicating. I leave the codes below.

Schema of Product, option-product and variant

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

Script for add and remove fields

$(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()

Product create and update

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

Product Params

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]])

function in application helper to add association

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

Product model

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

Option Product Model

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

  accepts_nested_attributes_for :variant, allow_destroy: true
end

Variant model

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 file

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

原文:https://stackoverflow.com/questions/39552566
更新时间:2024-02-02 20:02

最满意答案

程序看起来不错我猜你错过了分隔符

delimiter //
CREATE PROCEDURE dowhile()
  BEGIN
   DECLARE v1 INT DEFAULT 5;
    WHILE v1 > 0 DO
     SET v1 = v1 - 1;
   END WHILE;
 END; //
delimiter ;

The procedure looks ok I guess you are missing the delimiter

delimiter //
CREATE PROCEDURE dowhile()
  BEGIN
   DECLARE v1 INT DEFAULT 5;
    WHILE v1 > 0 DO
     SET v1 = v1 - 1;
   END WHILE;
 END; //
delimiter ;

相关问答

更多

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。