为了保持数据完整性,我需要防止某些模型在某些事件后被修改。例如,产品售出后不应该被注销。
我总是在控制器中实现它,就像这样(伪代码):
def ProductsController < ApplicationController
before_filter require_product_not_sold, :only => [ :write_off ]
private
def require_product_not_sold
if @product.sold?
redirect_to @product, :error => "You can't write off a product that has been sold"
end
end
end
让我感到震惊的是,我也可以在模型中做到这一点。像这样:
def Product < ActiveRecord::Base
before_update :require_product_not_sold
private
def require_product_not_sold
if self.written_off_changed?
# Add an error, fail validation etc. Prevent the model from saving
end
end
end
还要考虑可能有几个不同的事件需要产品尚未售出。
我喜欢控制器方法 - 您可以设置有意义的Flash消息,而不是添加验证错误。但感觉这个代码应该在模型中(例如,如果我想在我的Rails应用程序之外使用该模型)。
validates
而不是回调吗?什么是最干净的处理方式?感谢您的想法:)
答案 0 :(得分:2)
根据您的问题,您似乎已经覆盖了这个。理想情况下,模型应该知道如何保护其状态,因为数据对象通常在设计时考虑了可移植性(即使它们永远不会以这种方式使用)。
但在这种情况下,您希望在用户访问模型之前阻止操作。在这种情况下使用模型验证意味着你已经太晚了,用户已经进入并试图注销根据其销售状态永远无法访问的产品,因此已经超出了应有的范围。
所以我觉得理想的答案是“两者兼而有之”。该模型“应该”知道如何保护自己,作为备份,以防它在外部使用。
然而,在现实世界中,我们有不同的优先级和约束,因此我建议在可行的情况下实施您列出的更改,否则将其保存到下一个项目中。
就使用模型回调与验证而言,我认为这是一个棘手的问题,但我会进行验证,因为您可能希望向用户显示一条消息,并且正是为了这个用途而构建验证(我认为这更像是一个友好的和预期的用户错误,而不是与你可能处理不同的敌对或安全相关的错误。
这是否与你一直在考虑的一致?