看下面一个场景:
# 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默认的行为的
分享到:
- 2007-08-02 21:59
- 浏览 1882
- 评论(1)
- 论坛回复 / 浏览 (0 / 2939)
- 查看更多
相关推荐
Rails::API 是 Rails 的精简版本,针对不需要使用完整 Rails 功能的开发者。 Rails::API 移除了 ActionView 和其他一些渲染功能,不关心Web前端的开发者可更容易、快速地开发应用程序,因此运行速度比正常的 Rails ...
Ruby on Rails:ActiveRecord模型操作教程.docx
**ActiveRecord**是Ruby on Rails的核心组件之一,它提供了一种简洁的方式来进行数据库交互,通过模型对象(Models)将数据库表映射到程序中。这种方式简化了数据库操作,使得开发人员能够更加专注于业务逻辑而不是...
RailsAsyncMigrations ActiveRecord::Migration扩展程序以一种简单直接的方式使您的迁移异步。动机创建该库的目的是为了帮助在技术水平上难以扩展的小型公司。 小型项目不需要异步迁移队列,大公司在遇到扩展问题时...
Dan Chak他的著作Enterprise Rails 中的 我写的一篇关于物化视图的。 物化视图的。 安装 将gem 'materialized_views'添加到应用程序的 Gemfile 中,然后执行$ bundle 或者自己安装为$ gem install materialized_...
将ActiveRecord模型和JavaScript资产添加到swissmatch的rails中。 安装 安装gem: gem install swissmatch-rails 根据安装rubygems的方式,您必须使用sudo : sudo gem install swissmatch-rails 在Ruby中: require...
1. **快速开发**:Rails内置了许多实用的功能和库,如ActiveRecord ORM、MVC架构等,这些都能够极大地加快开发进度。 2. **代码简洁**:Rails遵循“约定优于配置”的原则,这意味着开发者无需编写大量重复代码就能...
Flowdock::Rails 这个 gem 添加了一个类方法来向特定流发送通知,以在启用的资源上创建和更新事件安装将此行添加到应用程序的 Gemfile 中: gem 'flowdock-rails'然后执行: $ bundle或者自己安装: $ gem install ...
ActiveRecord ::事件 ActiveRecord扩展提供了方便的时间戳管理方法。截屏 (由)安装将以下行添加到应用程序的Gemfile中: gem 'active_record-events' 使用Bundler安装gem: $ bundle install或通过运行以下命令...
向您的ActiveRecord模型添加友谊功能。 HasFriendship允许ActiveRecord对象使用自引用多态关联发送,接受和拒绝好友请求。 入门 将HasFriendship添加到您的Gemfile中: gem 'has_friendship' 捆绑HasFriendship...
数组元素支持对象:ActiveRecord,Mongid,哈希。 在您的Gemfile中: gem 'to_xls-rails' # Last officially released gem # gem "to_xls-rails", :git => "git://github....
Rails version 3.2.12 JavaScript Runtime therubyrhino (Rhino) Active Record version 3.2.12 Action Pack version 3.2.12 Active Resource version 3.2.12 Action Mailer version 3.2.12 Active Support ...
用 gem替换标准ActiveRecord#to_sql方法, 在控制台中输出漂亮SQL代码。 Rails日志也将被格式化。 输出示例: 或在控制台中 要求 Ruby2.4+ 滑轨 Rails 4.2+(可选),将自动注入 遗产 您可以将此版本的~> 0.2与...
stateful_enum是建立在ActiveRecord的内置ActiveRecord :: Enum之上的状态机gem。 安装 将此行添加到您的Rails应用程序的Gemfile中: gem 'stateful_enum' 和捆绑。 动机 您不需要抽象 stateful_enum取决于...
ActiveRecord模式源于Ruby on Rails,其核心思想是将数据库表与业务对象绑定,每个对象都代表一个数据库记录,并且包含操作这些记录的方法。这种模式简化了数据访问逻辑,使得开发者可以专注于业务逻辑的实现。 在...
1. **自动化的表映射**:ActiveRecord可以根据类名自动推断出对应的数据库表名,并根据类属性推断出表中的列。 2. **数据验证**:提供了丰富的验证规则,如唯一性验证、存在性验证等,确保数据的完整性和一致性。 3....
指数 描述和历史 Active Record Extended是对的原始作者Dan McClain所做的工作的延续。 随着时间的流逝,缺乏更新以支持最新版本的ActiveRecord 5.x的问题... 由于Rails / ActiveRecord / Arel被设计为与数据库无关,
rails generate acts_as_aliased:install rake db:migrate 这将创建一个新表aliases 。 用法 假设您有一个需要别名的模型Company ,因为公司名称有不同的版本。 使用acts_as_aliased在模型中启用别名: model ...
Rails 3.1 及以后版本的 ActiveRecord 查询API发生了重大变化,主要目的是为了提供更清晰、更可维护的代码,并且提高性能。在 Rails 2.x 中,许多使用哈希参数的查询方法如 `:conditions`, `:include`, `:joins` 等...
ActiveRecord::PostgreSQL::Expression 为 ActiveRecord PostgreSQL 适配器的迁移添加表达式。 安装 将此行添加到应用程序的 Gemfile 中: gem 'activerecord-postgresql-expression' 然后执行: $ bundle ...