无法在rails上销毁嵌套属性Ruby

时间:2016-11-07 00:16:06

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

我正在做电子商务。我的产品有很多产品选择,同时它们只有一个变体。我尝试使视图创建产品可以选择添加块,其中显示模型的字段以及与之关联的变体的更改。问题是当我去编辑带有变体的产品,并删除一个或两个,或者你想要的数量,而不是删除。

产品控制器

class ProductsController < ApplicationController
  before_action :set_product, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_admin_user!, only: [:new, :create, :edit, :update, :destroy]

  # GET /products
  # GET /products.json
  def index
    if admin_user_signed_in?
      @authenticate = true
    else 
      @authenticate = false
    end

    @products = Product.order(:index) # si vamos a todos los productos sin buscar nada

    if params[:search] # si hay parametro de busqueda
      @products = Product.where("name LIKE ?",  "%#{params[:search]}%") # buscamos todos los productos que tengan el mismo nombre
      if @products.length < 1 # si no hay al menos uno devolvemos todos los productos
        @products = Product.all
      end
    end
  end

  # GET /products/1
  # GET /products/1.json
  def show
    if admin_user_signed_in?
      @authenticate = true
    else 
      @authenticate = false
    end
  end

  # GET /products/new
  def new
    @product = Product.new
  end

  # GET /products/1/edit
  def edit
  end

  # POST /products
  # POST /products.json
  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

  # PATCH/PUT /products/1
  # PATCH/PUT /products/1.json
  def update
    products = Product.order(:index)
    indexOld = Product.where(:name => @product['name'])[0]['index'].to_i
    indexNew = product_params['index'].to_i # el producto que se va a actualizar
    if indexOld != indexNew
      for i in (indexNew - 1..indexOld - 1) # el indice nuevo simpre va a ser menor que el indice viejo 
        puts 'salida:'
        puts Product.find(products[i].id).update(:index => (products[i]['index'].to_i + 1).to_s)  # aumento en uno el indice del primer elemento a mover
      end
    end
    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

  # DELETE /products/1
  # DELETE /products/1.json
  def destroy
    index = @product.index
    products = Product.order(:index)
    products.each do |p|
      if p.index > index
        p.update(:index => p.index - 1)
        p.save
      end
    end
    DetailOrder.where(:product_id => @product.id).each do |detail|
      detail.destroy
      Order.find(detail.order_id).destroy
    end
    @product.destroy
    respond_to do |format|
      format.html { redirect_to products_url }
      format.json { head :no_content }
    end
  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.file_field :image2
  -if action_name == 'new'
    - if Product.order(:index).length > 0
      - index = Product.order(:index).last['index']
      = f.number_field :index, value: index + 1,:class => 'disp-none'
    - else
      = f.number_field :index, value: 1,:class => 'disp-none'
  -else
    .row
      .form-group.col-lg-6
        .field
          = f.number_field :index, :placeholder => 'Indice', value: @product.index, max: Product.order(:index).last['index'],:class => 'form-control input-border-left'
  .row
    .form-group.col-lg-6
      .field
        = f.number_field :stock, :placeholder => 'Stock', :class => 'form-control input-border-left'
  .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']), {}, {class: 'form-control input-border-left'}
  .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] }, {}, {class: 'form-control input-border-left'}

  .row
    .form-group.col-lg-6
      .field 
        = f.label :category_id
        %br/
        = f.select :category_id, Category.all.collect { |category| [category.name, category.id] }, {}, {class: 'form-control input-border-left'}
  .row
    .form-group.col-lg-6
      .field
        = f.label :Oferta
        %br/
        = f.check_box :offer
  .row
    .form-group.col-lg-6
      .field
        = f.text_field :nameVariants, :placeholder => 'Nombre para variantes', :class => 'form-control input-border-left'
  .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'

产品型号

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

  #accepts
  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: {large: "600x4600>", medium: "300x300>", thumb: "150x150#" }
  validates_attachment_content_type :image1, 
                                    content_type: /\Aimage\/.*\z/

  has_attached_file :image2, 
                    styles: {large: "600x4600>", medium: "300x300>", thumb: "150x150#" }
  validates_attachment_content_type :image2, 
                                    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: {large: "600x4600>", medium: "300x300>", thumb: "150x150#" }
  validates_attachment_content_type :image, 
                                    content_type: /\Aimage\/.*\z/
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()

1 个答案:

答案 0 :(得分:0)

另一种可能的解决方案是使用cocoon gem,这样您就可以轻松实现产品的嵌套属性。 (这将把所有的JS都带给你视图,让你轻松实现这个)