Rails - 如何在从不同模型过滤之前更改验证模型?

时间:2014-01-07 21:32:52

标签: ruby-on-rails validation ruby-on-rails-3.2

模型 - Purchaseorder,Purchaseorderadjustments,Productvariant,Location,Locationinventory

我将库存存储在Locationinventory中,该库存存有location_id,productvariant_id和数量。

当我想创建一个购买订单时,就会出现这种情况。我使用purchaseorderadjustments作为购买订单的嵌套属性。购买订单has_many purchaseorderadjustments存储productvariant_id和数量。

我在使用过滤器之前创建,更新和销毁相关的locationinventory记录。现在一切都运行良好,除了你可以从没有它们的位置删除项目,数量只是负数。我想验证“From Location”是否有足够的库存产品变量转移到“To Location”。

我做错了吗?谢谢!

Rails 3.2.14

Purchaseorder.rb

class Purchaseorder < ActiveRecord::Base
  attr_accessible :fromlocation_id, :status_id, :tolocation_id, :user_id, :purchaseorderadjustments_attributes

  belongs_to :user
  belongs_to :status
  belongs_to :fromlocation, :class_name => "Location", :foreign_key => :fromlocation_id
  belongs_to :tolocation, :class_name => "Location", :foreign_key => :tolocation_id
  has_many :purchaseorderadjustments, :dependent => :destroy

  accepts_nested_attributes_for :purchaseorderadjustments, allow_destroy: true

end

Purchaseorderadjustment.rb

class Purchaseorderadjustment < ActiveRecord::Base
  attr_accessible :adjustmenttype_id, :productvariant_id, :purchaseorder_id, :quantity

  belongs_to :purchaseorder
  belongs_to :productvariant
  belongs_to :adjustmenttype

  validates_presence_of :quantity, :message => "You need a quantity for each product."

  # On creation of a purchaseorderadjustment go ahead and create the record for locationinventory
  before_create :create_locationinventory
  def create_locationinventory
    # Get some info before updating the locationinventory
    if fromlocationinventory = Locationinventory.find(:first, conditions: { :location_id => purchaseorder.fromlocation_id, :productvariant_id => productvariant_id })
      fromlocation_current_quantity = fromlocationinventory.quantity
    end
    if tolocationinventory = Locationinventory.find(:first, conditions: { :location_id => purchaseorder.tolocation_id, :productvariant_id => productvariant_id })
      tolocation_current_quantity = tolocationinventory.quantity
    end

    # Create or update the from locationinventory
    unless fromlocationinventory.nil?
      fromlocationinventory.quantity = fromlocation_current_quantity - quantity
      fromlocationinventory.save
    else
      new_fromlocationinventory = Locationinventory.new({ location_id: purchaseorder.fromlocation_id, productvariant_id: productvariant_id, quantity: 0 - quantity })
      new_fromlocationinventory.save
    end

    # Create or update the to locationinventory
    unless tolocationinventory.nil?
      tolocationinventory.quantity = tolocation_current_quantity + quantity
      tolocationinventory.save
    else
      new_tolocationinventory = Locationinventory.new({ location_id: purchaseorder.tolocation_id, productvariant_id: productvariant_id, quantity: quantity })
      new_tolocationinventory.save
    end

  end

  #On update of purchaseorderadjustment
  before_update :update_locationinventory
  def update_locationinventory
    # Get some info before updating the locationinventory
    fromlocationinventory = Locationinventory.find(:first, conditions: { :location_id => purchaseorder.fromlocation_id, :productvariant_id => productvariant_id })
    tolocationinventory = Locationinventory.find(:first, conditions: { :location_id => purchaseorder.tolocation_id, :productvariant_id => productvariant_id })
    fromlocation_current_quantity = fromlocationinventory.quantity
    tolocation_current_quantity = tolocationinventory.quantity

    fromlocationinventory.quantity = fromlocation_current_quantity - quantity + self.quantity_was
    fromlocationinventory.save

    tolocationinventory.quantity = tolocation_current_quantity + quantity - self.quantity_was
    tolocationinventory.save

  end

  #On destroy of purchaseorderadjustment
  before_destroy :destroy_locationinventory
  def destroy_locationinventory
    # Get some info before updating the locationinventory
    fromlocationinventory = Locationinventory.find(:first, conditions: { :location_id => purchaseorder.fromlocation_id, :productvariant_id => productvariant_id })
    tolocationinventory = Locationinventory.find(:first, conditions: { :location_id => purchaseorder.tolocation_id, :productvariant_id => productvariant_id })
    fromlocation_current_quantity = fromlocationinventory.quantity
    tolocation_current_quantity = tolocationinventory.quantity

    fromlocationinventory.quantity = fromlocation_current_quantity + quantity
    fromlocationinventory.save

    tolocationinventory.quantity = tolocation_current_quantity - quantity
    tolocationinventory.save

  end

end

productvariant.rb

class Productvariant < ActiveRecord::Base
  attr_accessible :barcode, :compare_at_price, :fulfillment_service, :grams, 
                  :inventory_management, :inventory_policy, :inventory_quantity, 
                  :option1, :option2, :option3, :position, :price, :product_id, 
                  :requires_shipping, :shopify_id, :sku, :taxable, :title, :shopify_product_id, :product_title

  belongs_to :product, primary_key: "shopify_id", foreign_key: "shopify_product_id"
  has_many :purchaseorderadjustments
  has_many :locationinventories

  def product_plus_variant
    "#{self.product.title} - #{self.title}"
  end
end

locationinventory.rb

class Locationinventory < ActiveRecord::Base
  attr_accessible :location_id, :productvariant_id, :quantity

  belongs_to :productvariant
  belongs_to :location

end

1 个答案:

答案 0 :(得分:1)

我会写这个答案,因为我觉得你提供了这么多代码,你可能会害怕一些回答者!

我们的经验如下:


<强>嵌套

您可以通过多种不同方式验证嵌套模型

您的问题与在accepts_nested_attributes_for中传递数据有关 - 您可以直接验证:

#app/models/purchase.rb
Class Purchase < ActiveRecord::Base
    has_many :purchase_items
    accepts_nested_attributes_for :purchase_items
end

#app/models/purchase_item.rb
Class PurchaseItem < ActiveRecord::Base
    belongs_to :purchase

    validates :name,
          presence: { message: "Your Purchase Needs Items!" } #Returns to initial form with this error
end

标准

如果您想基于其他模型conditionally validate,则必须使用inverse_of:在整个数据交易中保持对象可用:

#app/models/purchase.rb
Class Purchase < ActiveRecord::Base
    has_many :purchase_items, inverse_of: :purchase
    accepts_nested_attributes_for :purchase_items
end

#app/models/purchase_item.rb
Class PurchaseItem < ActiveRecord::Base
    belongs_to :purchase, inverse_of: :purchase_items

    validates :name,
          presence: { message: "Your Purchase Needs Items!" },
          if: :paid_with_card?

    private
    def paid_with_card?
        self.purchase.payment_method == "card"
    end

end