浏览 2939 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-08-02
# product.rb class Product < ActiveRecord::Base validates_presence_of :price def self.find_ordered find(:all, : order => 'name') end end # product_test.rb require File.dirname(__FILE__) + '/../test_helper' class ProductTest < Test::Unit::TestCase def test_find_ordered_should_order_products_by_name Product.delete_all basket = Product.create!(:name => 'Basket') apple = Product.create!(:name => 'Apple') assert_equal [apple, basket], Product.find_ordered end end 运行ProductTest,结果出错,因为Product的price有validates_presence_of声明 我们能否暂时将Product的validation关闭呢,比如: # product_test.rb require File.dirname(__FILE__) + '/../test_helper' class ProductTest < Test::Unit::TestCase def test_find_ordered_should_order_products_by_name disable_validation do Product.delete_all basket = Product.create!(:name => 'Basket') apple = Product.create!(:name => 'Apple') assert_equal [apple, basket], Product.find_ordered end end end 好,就让我们一起来打开ActiveRecord的盒子,Hack一把: # test_helper.rb class Test::Unit::TestCase self.use_transactional_fixtures = true self.use_instantiated_fixtures = false def disable_validation ActiveRecord::Base.disable_validation! yield ActiveRecord::Base.enable_validation! end end module ValidationDisabler def self.included(base) base.class_eval do extend ClassMethods alias_method_chain :valid?, :disable_check end end def valid_with_disable_check? if self.class.validation_disabled? true else valid_without_disable_check? end end module ClassMethods def disable_validation! @@disable_validation = true end def enable_validation! @@disable_validation = false end def validation_disabled? @@disable_validation ||= false end end end class ActiveRecord::Base include ValidationDisabler end 我们定义了disable_validation方法,先关闭validation,然后将控制权交给block执行,然后恢复validation 而ValidationDisabler模块的代码简直是优美无比! 我们首先定义self.included(base)方法 这个方法就像一个钩子,当下面我们打开ActiveRecord::Base类让它将ValidationDisabler include进来时触发 然后反过来让ActiveRecord::Base执行class_eval,让Base继承ValidationDisabler里的ClassMethods模块 并且给Base的valid?方法加上了AOP -- alias_method_chain valid_with_disable_check?先判断validation_disabled?,如果返回true(即validation被disable掉了),则valid?方法返回true 如果validation_disabled?返回false(即validation没有disable),则调用valid_without_disable_check?(正常执行valid?方法) ClassMethods模块里定义一个类变量@@disable_validation来决定是否关闭当前validation 如果大家留意Rails源码和许多Rails插件的源码的话,就会发现很多都是基于上述模式打开ActiveRecord、ActionController 等模块来修改Rails默认的行为的 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |