`

ActiveRecord验证和回调4

阅读更多

9 回调概述
回调是在对象生命周期中某一时刻调用的方法。在Active Record对象从数据库中创建、保存、更新、删除、验证和装载的时候就可以编写回调代码。

9.1 注册回调
使用回调有个规则就是要注册它们。就像平常使用方法一样,使用一个macro-style类方法来注册。
class User < ActiveRecord::Base
validates_presence_of :login, :email
before_validation :ensure_login_has_a_value

protected
def ensure_login_has_a_value
    if login.nil?
      self.login = email unless email.black?
    end
end
end
macro-style类方法也接受一个block,如果代码很短就可以考虑把它写在block中。
class User < ActiveRecord::Base
validates_presence_of :login, :email
before_create { |user| user.name = user.login.capitalize if user. name.blank ?}
end

声明回调方法是保护和私有,这是很有用的做法。如果是公共的,就能从外部其他模型中调用该方法。

10 验证回调

10.1 创建对象
* before_validation
* before_validation_on_create
* after_validation
* after_validation_on_create
* before_save
* before_create
* INSERT OPERATION
* after_create
* after_save

10.2 更新对象
* before_validation
* before_validation_on_update
* after_validation
* after_validation_on_update
* before_save
* before_update
* UPDATE OPERATION
* after_update
* after_save

10.3 删除对象
* before_destroy
* DELETE OPERATION
* after_destroy

10.4 after_initialize和after_find
使用new方法或者从数据库中载入记录就可以使用after_initialize。

当从数据库中载入记录时就可以使用after_find,如果两种方法都定义了,after_find是在after_initialize之前调用。
这两个回调方法和其它的有一点点不同,它们没有before_*的版本。而且注册他们唯一的方法就是定义方法。如果使用macro-style来注册的话,会被忽略掉。
class User < ActiveRecord::Base
def after_initialize
    puts "You have initialized an object!"
end
def after_find
    puts "You have found an object!"
end
end

>> User.new
You have initialize an object!
=> #<User id: nil>

>>User.first
You have found an object!
You have initialized an object!
=>#<User id: 1>

12 跳过回调
在验证时有些方法可以跳过回调,请小心使用这些方法。
* decrement
* decrement_counter
* delete
* delete_all
* find_by_sql
* increment
* increment_counter
* toggle
* update_all
* update_counters

13 终止执行
在模型中注册回调,它们按队列执行。这些队列将包含在模型的验证中,注册回调,数据库执行操作。
整个回调被封装起来,如果有回调方法执行并返回false或者抛出一个异常,回调就终止。

14 关系回调
回调可以通过模型关系工作,并且能够被它们定义。

class User < ActiveRecord::Base
has_many :posts, :dependent => :destroy
end

class Post < ActiveRecord::Base
after_destroy :log_destroy_action
def log_destroy_action
    puts 'Post destroyed'
end
end

>> user = User.first
=> #<User id:1>
>> user.posts.create!
=> #<Post id: 1, user_id: 1>
>> user.destroy
Post destroyed
=> #<User id: 1>

15 有条件的回调
和验证类似,回调也可以附加条件。使用:if和:unless选项,该选项可以使用符号、字符串和Proc对象作为参数。

15.1 使用符号的:if和:unless
使用的符号参数一般是指向一个方法,如果这个方法返回false,那么回调就不执行。
class Order < ActiveRecord::Base
before_save :normalize_card_number, :if => :paid_with_card?
end

15.2 使用字符串的:if和:unless
字符串参数是可能通过eval执行的Ruby代码。当描述一个很短的条件时可以用它。
class Order < ActiveRecord::Base
before_save :normalize_card_number, :if => "paid_with_card?"
end

15.3 使用Proc对象的:if和:unless
通过条件在一行时,使用这个参数是再好不过的了。
class Order < ActiveRecord::Base
before_save :normalize_card_number,
    :if => Prod.new{|order| order.paid_with_card?}
end

15.4 多条件的回调
当用条件来限制回调时,可以把:if和:unless同时写上。
class Comment < ActiveRecord::Base
after_create :send_email_to_author, :if => :author_wants_emails?,
    :unless => Proc.new{ |comment| comment.post.ingnore_comment?}
end

16 回调类
虽然多数情况下,使用内建的回调方就足够了。ActiveRecord也让你可以自己定义类来创建回调方法,而且这个过程很容易。
class PictureFileCallbacks
def after_destroy(picture_file)
    File.delete(picture_file.filepath) if File.exists?(picture_file.filepath)
end
end

当在类中声明一个回调方法,会用模型对象作为参数。可以这样来使用:
class PictureFile < ActiveRecord::Base
after_destroy PictureFileCallbacks.new
end
我们声了一个回调的实例方法,这样就要实例化一个PictureFileCallbacks对象。很多时候会用类方法:
class PictureFileCallbacks
def self.after_destroy(picture_file)
    File.delete(picture_file.filepath) if File.exists?(picture_file.filepath)
end
end

如果回调方法是这样定义的,就不用实例化了。
class PictureFile < ActiveRecord::Base
after_destroy PictureFileCallbacks
end

17 观察者
观察者和回调类似,但又有很大的不同。回调会意图污染没有直接关系的模型,而观察者允许你在模型的外部添加同样的功能。例如:有一个User模型,没有包含发送验证邮件的代码,应当考虑使用观察者。

17.1 创建观察者
例如,User模型要为每个新创建的用户发送email。因为发送email和我们的模型没有直接的联系,所以就创建观察者来包含这些功能。
class UserObserver < ActiveRecord::Observer
def after_create(model)
    # code to send confirmation email...
end
end

和回调类一样,观察者方法接受观察者模型作为参数。

17.2 注册观察者
观察者一惯是放在app/models目录和在config/enviroment.rb中注册。上面例子UserObserver应保存在app/models/user_observer.rb文件中和在config/environment.rb中加上:
config.active_record.observers = :user_observer

17.3 共享观察者
观察者可以添加到更多的模型中:
class MailerObserver < ActiveRecord::Observer
observe :registration, :user
def after_create(model)
    # code to send cofirmation email...
end
end

这个例子中,每当一个Registration或者User创建的时候,就会调用after_create方法。要注意的就是新的MailerObserver观察者要注册到config/environment.rb中。
config.active_record.observers = :mailer_observer

 

form:http://hi.baidu.com/haifreeidea/blog/item/6b6bfdef6f96aef3b0fb9566.html

分享到:
评论

相关推荐

    Pro ActiveRecord Databases with Ruby and Rails.pdf

    5. **回调**: 在模型的生命周期中可以定义各种回调函数,例如在保存之前或之后执行某些操作。 6. **自定义方法**: 可以在模型类中定义自定义的方法,实现特定的业务逻辑。 #### 五、高级用法 1. **分页**: 使用...

    ActiveRecord简单实例代码.zip

    ActiveRecord支持在特定生命周期事件(如创建、更新、删除等)前后执行的回调函数。例如,`before_save :normalize_email`会在保存用户前自动规范化电子邮件地址。 8. **序列化** ActiveRecord允许你序列化复杂的...

    sneaky-save:允许更新复杂的对象而无需触发验证或回调

    允许保存记录而无需调用回调和验证。 正在安装 $ gem install sneaky-save 或放入您的gemfile以获取最新版本: gem 'sneaky-save' , git : 'git://github.com/einzige/sneaky-save.git' 使用 # Update. Returns ...

    noar:NodeJS ActiveRecord

    事务(基于异步钩子,因此您无需将代码包装到回调中) 基于knex.js(因此您拥有knex查询构建器的所有功能) 声明范围,关系,验证 Yaml夹具,用于播种测试数据并在测试中使用 级联保存 包含有限状态机 容易的多态...

    Ruby-ActiveModel的自定义验证用于检查数组是否包含在另一个中

    在ActiveModel中,可以通过定义一个验证方法并在`validate`回调中调用来实现。下面是一个简单的示例: ```ruby class MyModel attr_accessor :input_array validate :intersection_validation private def ...

    from-activerecord-to-ecto:包含示例的指南,以帮助从ActiveRecord过渡到Ecto

    开发人员使用ActiveRecord所做的大部分工作都使数据模型对所有使用者都具有相同的功能(通过使用验证和回调),而Ecto鼓励使用不太严格的行为。 尽管可以在ActiveRecord中定义这些边界(请考虑 ),但是某些应用...

    Ruby on Rails 指南 v5.0.1 中文版

    - **回调**:解释ActiveRecord中可用的生命周期回调,以及如何利用这些回调增强模型的功能。 - **迁移**:介绍如何使用迁移来管理和维护数据库结构的变化。 #### ActiveRecord迁移 - **迁移概述**:解释迁移的概念...

    验证_锻炼

    1. **ActiveRecord验证**:在Ruby on Rails中,ActiveRecord模型提供了内置的验证工具,例如`validates`, `validates_format_of`, `validates_length_of`等,这些方法可以帮助开发者检查模型实例的数据是否符合预设...

    active_type:使任何Ruby对象像ActiveRecord一样发出嘎嘎声

    但是,我们不想失去ActiveRecord的便利,例如验证,回调等。 用例示例是支持登录的模型: class SignIn &lt; ActiveType :: Object # this is not backed by a db table attribute :username , :string ...

    ActiveRecord生命周期阅读v-000

    目标了解AR生命周期方法的概念使用before_save , before_create和before_validation 了解何时使用before_validation与before_save回呼现在,我们将ActiveRecord集成到Rails中,我们应该注意,只要模型中发生某些...

    activerecord-lifecycle-reading-onl01-seng-ft-050420

    我们在这里介绍的所有内容都称为“活动记录生命周期回调”。 很多人都称它们为回调。 有点短。 看一下其中包含的博客应用程序。 在开始向Rails学习之前,请确保运行迁移(我们使用rake db:migrate做到了!)! ...

    activerecord-lifecycle-reading-online-web-sp-000

    我们在这里介绍的所有内容都称为“活动记录生命周期回调”。很多人都称它们为回调。有点短。 看一下其中包含的博客应用程序。在开始向Rails学习之前,请确保运行迁移(我们使用rake db:migrate做到了!)!我们有一...

    serialize_has_many:将has_many关系序列化为单个列。 使用ActiveRecord轻松实现NoSQL!

    serialize_has_many 将has_many关系序列化为单个列,同时仍在进行属性,验证,回调,嵌套表单和fields_for。 使用ActiveRecord轻松实现NoSQL!安装将此行添加到您的应用程序的Gemfile中: gem 'serialize_has_many' ...

    RoR 培训课程PPT

    - **关联、验证及回调**:深入讲解ActiveRecord中的关联关系(如一对一、一对多等),以及如何进行数据验证和回调函数的应用。 - **ActionView表单**:学习如何在视图层构建动态表单,利用ActionView提供的模板...

    sequel-activemodel-源码.rar

    Sequel Activemodel的结合使得在Sequel中可以使用ActiveRecord的一些特性,如验证、序列化和回调等,增强了Sequel的功能性和灵活性。 首先,我们来看看Sequel的核心概念。Sequel的核心是Dataset对象,它代表了...

    Ruby-OmniAuth利用Rack中间件的一个灵活认证系统

    OmniAuth 中间件会处理这个回调,解析出用户的标识符(通常称为 "uid")和其他信息,然后这些信息可以通过 `request.env['omniauth.auth']` 访问。 OmniAuth 还提供了丰富的自定义选项,比如可以在回调处理中添加...

    Ruby-ActiveAttr一组模块让用户可以更方便地创建普通带功能的Ruby模型

    5. **Callbacks**:回调机制,可以在特定事件(如`before_create`、`after_update`等)发生时执行代码。 6. **Typecasting**:类型转换,允许你指定属性的类型,如`attribute :age, type: Integer`,自动将字符串...

    rails-2.3.3.zip

    在2.3.3版中,ActiveRecord支持复杂的查询,如关联(associations)和回调(callbacks),以及ActiveRecord验证(validations)确保数据的完整性。 3. **ActionController**:处理HTTP请求并生成响应。在2.3.3中,...

    Ruby on Rails源代码

    你可以学习如何定义属性、关系(如一对多、多对多)、验证和回调。 3. **控制器**:`app/controllers`目录下的文件是Rails应用的核心部分,它们处理HTTP请求并调用模型和视图。控制器类定义了各种行动,这些行动...

    Laravel开发-laravel-goodies .zip

    11. **事件系统(Event System)**:Laravel的事件系统允许开发者在特定时刻触发回调函数,实现松耦合的事件监听。 12. **邮件系统(Email System)**:Laravel集成了SwiftMailer库,支持发送HTML和文本邮件,可以...

Global site tag (gtag.js) - Google Analytics