`
jbf034
  • 浏览: 153193 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Callback Objects

阅读更多
可在“模型”类内直接指定回调处理器,你可以创建分离的处理器类,它封装所有回调
方法。这些处理器可以在多个“模型”间共享。一个处理器类是个简单的类,它定义回调方
法(before_save(),after_create(),等等)。在app/models 目录内为这些处理器类创建源
文件。
在“模型”对象内使用处理器,你创建这个处理器类的实例,并传递那个实例给各种回
调定义。几个例子会让这些更清楚些。
如果我们应用程序在多个地方使用信用卡,我们可能想在多个方法内共享我们的
normalize_credit_card_number()方法。要做到这点,我们要抽取方法到它自己的类中并在
我们希望它处理的事件名后命名它。这个方法将接受单个参数,回调被生成的“模型”对象。
class CreditCardCallbacks
# Normalize the credit card number
def before_validation(model)
model.cc_number.gsub!(/-w/, '')
end
end
现在,在我们的“模型”类中,我们可以重排这个被调用的共享的回调。
class Order < ActiveRecord::Base
before_validation CreditCardCallbacks.new
# ...
end
class Subscription < ActiveRecord::Base
before_validation CreditCardCallbacks.new
# ...
end
这个例子中,处理器类假设信用卡号码被保存在一个“模型”属性cc_number 内,Order
和Subscription 两者将有一个与之同名的属性。但是我们可以推广这个思想,让处理器类减
少对使用它的类的实现细节的依赖。
例如,我们可以创建一个普通的加密和解密处理器。这可以在它们被存储到数据库之前
加密名字字段,并在行被读回时解密它们。你可以做为一个回调处理器包括它在任何需要此
功能的“模型”内。
处理需要在“模型”数据被写回数据库之前,加密一个“模型”内给出的属性集。因为
我们的应用程序需要处理这些属性的文本文件,完成存储之间它重新排列及解密它们。它也
需要在行被从数据库读入到一个“模型”对象时解密这些数据。这些要求意味着我们需要在
保存数据和找到一个新行时解密数据库行,我们可以通过别名after_find()方法为
after_save()—同一个方法有两个名字,来保存代码。
class Encrypter
# We're passed a list of attributes that should
# be stored encrypted in the database
def initialize(attrs_to_manage)
@attrs_to_manage = attrs_to_manage
end
# Before saving or updating, encrypt the fields using the NSA and
# DHS approved Shift Cipher
def before_save(model)
@attrs_to_manage.each do |field|
model[field].tr!("a-z", "b-za")
end
end
# After saving, decrypt them back
def after_save(model)
@attrs_to_manage.each do |field|
model[field].tr!("b-za", "a-z")
end
end
# Do the same after finding an existing record
alias_method :after_find, :after_save
end
我们现在可以重排从我们的orders“模型”内调用的Encrypter 类。
require "encrypter"
class Order < ActiveRecord::Base
encrypter = Encrypter.new(:name, :email)
before_save encrypter
after_save encrypter
after_find encrypter
protected
def after_find
end
end
我们创建一个新的Encrypter 对象并用它钩住before_save,after_save,和after_find
事件。这种方式,在一个定单被保存之前,encrypter 内的方法before_save()将被调用,等
等。
那么,我们为什么要定义一个空的after_find()方法呢?记住我们说过,出于性能的原
因after_find 和after_initialize 被视为是特别的。这种特殊对待的结果之一是“活动记
录”不想知道调用一个after_finde 处理器,除非它在“模型”类中看到一个真实的
after_find()方法。我们必须定义一个空的占位符给after_find 处理。
This is all very well, but every model class that wants to make use of our
encryption handler would need to include some eight lines of code, 就像我们在
Order 类内做的那样。我们会做的更好,我们将定义一个帮助方法,它完成所有工作,并且
让那个帮助方法对所有“活动记录模型”都是有效的。要做到这些,我们将添加它到
ActiveRecord::Base 类中。
class ActiveRecord::Base
def self.encrypt(*attr_names)
encrypter = Encrypter.new(attr_names)
before_save encrypter
after_save encrypter
after_find encrypter
define_method(:after_find) { }
end
end
像这样,我们现在可以使用单个调用来添加encryption 给任何“模型”类的属性。
class Order < ActiveRecord::Base
encrypt(:name, :email)
end
一个简单的驱动程序让我们来检验这个。
o = Order.new
o.name = "Dave Thomas"
o.address = "123 The Street"
o.email = "dave@pragprog.com"
o.save
puts o.name
o = Order.find(o.id)
puts o.name
在控制台,我们在“模型”对象内看到我们的消费者的名字。
ar> ruby encrypt.rb
Dave Thomas
Dave Thomas
但是,在数据库中,很明显名字和email 地址被加密了。
分享到:
评论

相关推荐

    openapi3.0

    8. **回调对象(Callback Objects)**:定义了异步操作的响应,使得API能够支持WebSockets或其他非HTTP协议。例如: ```yaml callbacks: myCallback: 'https://example.com/event': post: requestBody: ...

    理解javascript中的回调函数(callback)

    首先,我们要认识到JavaScript中函数是第一类对象(first-class objects),这意味着函数可以像任何其他对象一样被创建、赋值给变量、作为参数传递给函数或作为其他函数的返回值。这种特性使***ript函数更加灵活。举...

    [Mastering.Node.js(2013.11) 精通Node.js

    Working with objects 240 Using AWS with a Node server 243 Getting and setting data with DynamoDB 244 Searching the database 247 Sending mail via SES 248 Authenticating with Facebook Connect 250 ...

    python3.6.5参考手册 chm

    Python参考手册,官方正式版参考手册,chm版。以下摘取部分内容:Navigation index modules | next | Python » 3.6.5 Documentation » Python Documentation contents What’s New in Python ...

    Nodejs学习笔记之Global Objects全局对象

    在Node.js中,全局对象(Global Objects)扮演着至关重要的角色,它是所有模块都能访问的一组预定义的对象和函数。与浏览器环境不同,Node.js的顶级作用域并非全局作用域,而是模块作用域。这意味着在Node.js的模块...

    Java消息处理与回调.docx

    - 例如,我们定义了一个`CallBack`接口,其中包含一个`execute`方法,用于处理异步操作的结果。 #### 四、Java代码实现示例 下面通过具体的Java代码示例来展示如何实现异步处理和回调。 ##### 1. 回调接口定义 ...

    Perl extension module for Tuxedo

    * callback subs perl subs can be registered as unsolicited message handlers and signal handlers. * FML/FML32 field table support This module includes the mkfldpm32.pl script that is the perl ...

    tornado.pdf

    You can also use IOLoop.run_in_executor to asynchronously run a blocking function on another thread, but note that the function passed to run_in_executor should avoid referencing any Tornado objects....

    Android.Games.Practical.Programming.By.Example.Quickstart

    You'll be able to implement the activity's lifecycle callback methods and utilize handlers to switch views in game. This unit also goes into detail on how to write the main thread and view for your ...

    JavaScript-Objects-Extensions-for-Meteor:Meteor 的有用 JavaScript 对象扩展

    Object.defineReactiveProperty(target, prop, value, callback, getCallback, setCallback) - 用回调定义React属性: 在 Setter 和 Getter 之前设置回调 在 Setter 上设置回调 在 Getter 上设置回调 someArray.in...

    nodejs中文帮助文档.pdf

    - **GlobalObjects全局对象** - **定义**: Node.js提供了一系列全局可用的对象,用于简化开发过程。 - **重要全局对象**: - `process`: 提供了访问Node.js进程信息和控制流程的方法。 - `Buffer`: 处理二进制...

    MATLAB可视化界面设计.doc

    控件对象的辅助属性包括 Callback 管理属性,如 BusyAction、ButtonDownFun、CreateFun、DeletFun 等,可以用来控制控件对象的 callback 行为。控件对象的修饰控制属性包括 FontAngle、FontName、FontUnits、...

    QHierarchy 4.2 最新版Unity插件

    - Displaying the error icon (MonoBehaviour script missing / Reference property is null / String property is empty / Callback of event is missing) - Displaying icons of all scripts that attached to a ...

    CGlib动态代理类的jar包

    此外,CGlib还适用于创建测试桩对象(mock objects)以及在运行时修改类的行为。 总的来说,CGlib是一个强大的工具,它通过字节码生成技术为Java开发者提供了丰富的可能性,不仅在动态代理上有广泛应用,还在许多...

    Android平台下的RTP,RTCP实现

    Participant - participant objects DataFrame - the containers in which data is returned RTPAppIntf - the mininum callback interface RTPCAppIntf - optional interface for receing RTCP packets ...

    Node.js中文文档

    #### 六、GlobalObjects 全局对象 - **process**:提供了关于当前 Node.js 进程的信息以及控制它的方法。 - `process.exit(code)`:退出当前进程。 - `process.pid`:进程 ID。 - `process.platform`:运行平台...

    callbag-connect-react

    npm install callbag-connect-react 用法import connect from 'callbag-connect-react@connect( { // Objects are assumed to contain sourcess propName: source1, ... }, [ // Arrays are assumed to contain ...

    android 访问网络接口+json解析(包含list)

    - 发送请求:通过`OkHttpClient`的`newCall(request).enqueue(callback)`异步发送请求,并在回调中处理响应。 2. JSON解析: - Android SDK提供了`org.json`库,但它的性能和功能有限。推荐使用Gson或Jackson库,...

    Effective C#

    - **Purpose:** Delegates provide a way to pass methods as arguments, enabling callback mechanisms. - **Example:** ```csharp public delegate void ActionHandler(object sender, EventArgs e); public ...

    MATLAB GUI实现动态画图曲线的源程序matlab代码.zip

    2. **回调函数(Callback Functions)**:当用户操作GUI组件时,相应的回调函数会被调用。这些函数定义了GUI的行为和响应。 3. **布局管理(Layout Management)**:MATLAB中的布局管理器如GUIDE(Graphical User ...

Global site tag (gtag.js) - Google Analytics