2009-11-18 119 views
0

验证:check_product_stock自定义验证需要帮助

def check_product_stock 

    @thisproduct = product.id 

    @productbeingchecked = Product.find_by_id(@thisproduct) 

    @stocknumber = @productbeingchecked.stock_number 

    if producto.en_stock == 0 
    raise "El Producto no tiene stock suficiente para completar la venta" 

    #errors.add :venta, "Producto con pedos de stock" 
    return false 
    end 
true 
end 

end 

我需要能够验证上创建一个模型(销售)的,如果协会(产品),并没有在product.column达到零称为stock_number。

我想我需要重写整个事情,但现在验证:check_product_stock然后建立一个从头开始检查产品是否没有达到零的方法,它有它应该抛出一个Flash通知,并留在同一个地方(销售/新)

class Venta < ActiveRecord::Base 

    hobo_model # Don't put anything above this 

    belongs_to :cliente, :accessible => true 
    belongs_to :producto, :accessible => true 
    belongs_to :marca, :accessible => true 
    belongs_to :vendedor 
    belongs_to :instalador 
    has_many :devolucions 



    fields do 
    numero_de_serie  :string 
    precio_de_venta  :integer 
    precio_de_instalacion :integer, :default => "0" 
    forma_de_pago enum_string(:contado, :tarjeta) 
    status enum_string(:activa, :cancelada) 
    timestamps 
    end 

    validates_presence_of :cliente, :precio_de_venta, :vendedor, :precio_de_instalacion 

    validate_on_create :check_product_stock 

    after_save :descontar_precio_de_instalacion_si_el_instalador_es_a_destajo 

#def stock_error 

    #flash[:notice] = "Producto con pedos de stock" 

# redirect_to :controller => :venta, :action => :stock_error 

    #errors.add_to_base("Producto con pedos de stock") 

# end 

def check_product_stock 

if producto.en_stock == 0 
raise "El Producto no tiene stock suficiente para completar la venta" 

#errors.add :venta, "Producto con pedos de stock" 
    return false 
    end 
true 
end 

#def check_product_stock 
# if producto.en_stock == 0 
# errors.add :producto, "El Producto no tiene stock suficiente para completar la venta" 
# return false 
# end 
# true # guards against returning nil which is interpreted as false. 
#end 




def descontar_precio_de_instalacion_si_el_instalador_es_a_destajo 





    @este_instalador_id = instalador.id 

    @instalador = Instalador.find_by_id(@este_instalador_id) 


    if @instalador.a_destajo? 

    @last_venta = Venta.find(:last) 

    @vid = @last_venta.id 

    @precio_de_instalacion_original = precio_de_instalacion 

    @mitad_de_instalacion = @precio_de_instalacion_original/2 

    #Venta.update(@vid, :precio_de_instalacion => @mitad_de_instalacion) 

    ActiveRecord::Base.connection.execute "UPDATE ventas SET precio_de_instalacion = #{@mitad_de_instalacion} WHERE id = #{@vid};" 



    end 


end 








#after_save :reduce_product_stock_number 

# def reduce_product_stock_number 
# Producto.decrement_counter(:en_stock, producto.id) 
# end 




    # --- Permissions --- # 

    def create_permitted? 
    true 
    end 

    def update_permitted? 
    false 
    end 

    def destroy_permitted? 
    false 
    end 

    def view_permitted?(field) 
    true 
    end 

end 

这是我的观察,从PRODUCTO削弱了en_stock柱:

class VentaObserver < ActiveRecord::Observer 

def after_save(venta) 

     @venta_as_array = venta 




     if venta.producto_id? 

     @pid = @venta_as_array[:producto_id] 

     Producto.decrement_counter(:en_stock, @pid) 

     end 

     if venta.cart_id 

     @cid = @venta_as_array[:cart_id] 

     @cart = Cart.find_by_id(@cid) 

     for item in @cart.cart_items do 
     # @pid = @cart.cart_items.producto.id 



      Producto.decrement_counter(:en_stock, item.producto.id) 

     end 

     #si el instalador es a destajo se debe descontar la mitad del rpecio de instalacion 






     end 

end 

end 

回答

4

看来你在这里有很多错误。

首先,你做的工作太多了。这是你真正需要的。其次,闪存散列在模型中不可用。您可以使用ActiveRecord的错误对象通过errors.add_to_base

我用errors.add_to_base因为错误是不是这个模式完全是一个部分,但仍然阻挡替换

flash[:notice] =,以提供给控制器和错误观点保存。

第三,似乎你正在减少product.stocknumber在某个时刻。可能作为before_validation,因此在检查product.stocknumber在保存调用之前是否为0期间,product.stocknumber很可能小于0。

所以让我们改变if条件来反映这一点。

unless product.stocknumber > 0 

最后,您正在使用before_save回调,因此只需添加错误将不会取消事务。您需要在save/create/update/valdiaiton回调之前/之后返回false来取消事务。

把所有这些组合起来给你

before_save :check_product_stock 

def check_product_stock 
    unless product.stocknumber > 0 
    errors.add_to_base "Producto con pedos de stock" 
    return false 
    end 
    true # guards against returning nil which is interpreted as false. 
end 

至于显示这些错误,你可以用好的error_messages_for助手视图的对象。或者将错误复制到控制器中的闪存散列中。

在视图:

<%= error_mesages_for :order %> 

,或者在的if @order.save else块控制器:

flash[:errors] = @order.errors.full_messages.join "<br />" 

我更喜欢在通知中的错误,当谈到传球失误在闪存哈希因为如果一个动作同时产生一个通知或一个错误,它可以很容易地通过CSS区分这两个CSS。此外,它总是显示闪存[:错误],并提供红色文本,将逻辑写入视图以确定flash [:notice]的内容是错误还是通知。

2

闪光灯在模型中可用。您需要这样做:

errors.add :stocknumber, "Producto con pedos de stock" 

然后在控制器和视图中使用flash。

+0

我迷路了,你能深入这个吗?在此先感谢,我想要的是检查是否与主模型(venta)的关联(producto)在en_stock字段中未达到零。 – 2009-11-18 02:27:00

+0

你的代码基本上没问题。唯一的问题是对ActiveRecord模型中无法访问的flash []的调用。在ActiveRecord中处理错误的正确方法是调用errors.add。 – 2009-11-18 03:05:24

+0

如果我这样做的:def check_product_stock @thisproduct = producto.id @productbeingchecked = Producto.find_by_id(@thisproduct) @stocknumber = @ productbeingchecked.en_stock 如果@stocknumber == 0 errors.add:stocknumber ,“El producto tiene zero existencias disponibles,por lo tanto no puede completarse la venta。” 结束 结束 我得到-1时尝试使用零库存的产品进行销售,所以它是毫无意义的 – 2009-11-18 03:15:25