guides.rubyonrails.org 读书笔记(五)
来源:互联网 发布:涨乐理财软件下载 编辑:程序博客网 时间:2024/05/29 16:05
Active Record Validations and Callbacks
1 The Object Life Cycle
Active Record provides hooks into this object life cycle so that you can control your application and its data. 保证Rails object在创建、更新、销毁过程都是可控的。
(1)Validations allow you to ensure that only valid data is stored in your database.
(2)Callbacks and observers allow you to trigger logic before or after an alteration of an object’s state.
2 Validations Overview
2.1 Why Use Validations?
Validations are used to ensure that only valid data is saved into your database. For example, it may be important to your application to ensure that every user provides a valid email address and mailing address.
There are several ways to validate data before it is saved into your database, including
(1)native database constraints,
不利于测试和维护,但是在有另外的程序,比如来自移动API,同时使用这个数据库时,数据库层面的校验就非常重要了。
(2)client-side validations,
快速反应,但客户端不易于控制,比如客户可能关闭来javascript
(3)controller-level validations,
这个层面的控制其实也是可以的,并不会如guide所说的那样不利于测试和维护。但是为了
(1)控制器本身的逻辑代码就不少,把校验移动出去,可以减少控制器的逻辑代码,防止fat
(2)遵从习惯,易于代码的传承管理,交接维护。
(4) model-level validations.
2.2 When Does Validation Happen?
There are two kinds of Active Record objects: those that correspond to a row inside your database and those that do not.
Validations are typically run before these commands are sent to the database. If any validations fail, the object will be marked as invalid and Active Record will not perform the INSERT or UPDATE operation.
Creating and saving a new record will send an SQL INSERT operation to the database. Updating an existing record will send an SQL UPDATE operation instead. Validations are typically run before these commands are sent to the database.
(1) 部分方法会触发校验;
(2)部分方法不会;
(3)save(:validate => false)
Note that save also has the ability to skip validations if passed :validate => false as argument. This technique should be used with caution.
2.4 valid? and invalid?
You can also use this method on your own. valid? triggers your validations and returns true if no errors were added to the object, and false otherwise.这里的原理其实很简单,校验失败后,对应的错误信息会被收集起来。而Active:Record也就是通过最终的错误信息来判断一个对象是否有效。也就是下面这句话的含义。
When Active Record is performing validations, any errors found can be accessed through the errors instance method. By definition an object is valid if this collection is empty after running validations.
而此校验有两种方式:
(1)直接运行valid?
>> p.valid?
=>
false
>> p.errors
=> {
:name
=>[
"can't be blank"
]}
(2)会触发校验的方法:
>> p = Person.create
=>
#<Person id: nil, name: nil>
>> p.errors
=> {
:name
=>[
"can't be blank"
]}
Note that an object instantiated with new will not report errors even if it’s technically invalid, because validations are not run when using new.下面的程序就反映了这个问题,
class
Person < ActiveRecord::Base
validates_presence_of
:name
end
>> Person.
new
.errors[
:name
].any?
# => false
>> Person.create.errors[
:name
].any?
# => true
2.5 errors[]
上面这段程序还值得关注的是errors。To verify whether or not a particular attribute of an object is valid, you can use errors[:attribute]. It returns an array of all the errors for :attribute. If there are no errors on the specified attribute, an empty array is returned.
ruby-1.9.2-p180 :013 > ps = Post.create(:name=>"", :title=>"jess")
=> #<Post id: nil, name: "", title: "jess", content: nil, created_at: nil, updated_at: nil>
ruby-1.9.2-p180 :014 > ps.valid?
=> false
ruby-1.9.2-p180 :015 > ps.errors
=> {:name=>["can't be blank"], :title=>["is too short (minimum is 5 characters)"]}
3 Validation Helpers
Active Record offers many pre-defined validation helpers that you can use directly inside your class definitions. These helpers provide common validation rules. Every time a validation fails, an error message is added to the object’s errors collection, and this message is associated with the field being validated.
Each helper accepts an arbitrary(任意的) number of attribute names, so with a single line of code you can add the same kind of validation to several attributes.
All of them accept the :on and :message options, which define when the validation should be run and what message should be added to the errors collection if it fails, respectively. The :on option takes one of the values :save (the default), :create or :update. There is a default error message for each one of the validation helpers. These messages are used when the :message option isn’t specified. Let’s take a look at each one of the available helpers.
(1)validates_format_of,regular expression
(3)validates_length_of
The default error messages depend on the type of length validation being performed. You can personalize these messages using the :wrong_length, :too_long, and :too_short options and %{count} as a placeholder for the number corresponding to the length constraint being used. You can still use the :message option to specify an error message.
This helper counts characters by default, but you can split the value in a different way using the :tokenizer option.
(4) validates_presence_of
If you want to be sure that an association is present, you’ll need to test whether the foreign key used to map the association is present, and not the associated object itself.
class
LineItem < ActiveRecord::Base
belongs_to
:order
validates_presence_of
:order_id
end
4 Common Validation Options
4.4 :on
5 Conditional Validation
Sometimes it will make sense to validate an object just when a given predicate is satisfied. You can do that by using the :if and :unless options, which can take a symbol, a string or a Proc.
6 Creating Custom Validation Methods
You can pass more than one symbol for each class method and the respective validations will be run in the same order as they were registered.
7 Working with Validation Errors
7.1 errors
Returns an OrderedHash with all errors. Each key is the attribute name and the value is an array of strings with all errors.
person.errors# => {:name => ["can't be blank", "is too short (minimum is 3 characters)"]}
7.2 errors[]errors[] is used when you want to check the error messages for a specific attribute.
8 Displaying Validation Errors in the View
8.1 error_messages and error_messages_for
You can also use the error_messages_for helper to display the error messages of a model assigned to a view template. It’s very similar to the previous example and will achieve exactly the same result.
在模板中使用:
<%=
error_messages_for
:product
%>
9 Callbacks Overview
Callbacks are methods that get called at certain moments of an object’s life cycle. With callbacks it’s possible to write code that will run whenever an Active Record object is created, saved, updated, deleted, validated, or loaded from the database.
9.1 Callback Registration
In order to use the available callbacks, you need to register them. You can do that by implementing them as ordinary methods, and then using a macro-style class method to register them as callbacks.
It’s considered good practice to declare callback methods as being protected or private. If left public, they can be called from outside of the model and violate the principle of object encapsulation.
10 Available Callbacks
after_save runs both on create and update, but always after the more specific callbacks after_create and after_update, no matter the order in which the macro calls were executed.
The after_initialize callback will be called whenever an Active Record object is instantiated, either by directly using new or when a record is loaded from the database. It can be useful to avoid the need to directly override your Active Record initialize method.
The after_find callback will be called whenever Active Record loads a record from the database. after_find is called before after_initialize if both are defined.
11 Running Callbacks
The after_initialize callback is triggered every time a new object of the class is initialized.
12 Skipping Callbacks
13 Halting Execution
As you start registering new callbacks for your models, they will be queued for execution. This queue will include all your model’s validations, the registered callbacks, and the database operation to be executed.
The whole callback chain is wrapped in a transaction. If any before callback method returns exactly false or raises an exception, the execution chain gets halted and a ROLLBACK is issued; after callbacks can only accomplish that by raising an exception.
这个带来的影响还需要进一步估计,比如操作或者交易的中途中断。
14 Relational Callbacks
建立两个model直接的callback关系,但就以下的例子而言,说明不了什么问题。 User.destroy后,因为:dependent => :destroy,所以对应的Post也会被删除,间而 after_destroy :log_destroy_action被触发。由此可见,after_destroy本质上还是由post自身的destroy引起的。
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 Conditional Callbacks
You can do that by using the :if and :unless options, which can take a symbol, a string or a Proc.
16 Callback Classes
Sometimes the callback methods that you’ll write will be useful enough to be reused by other models. Active Record makes it possible to create classes that encapsulate the callback methods, so it becomes very easy to reuse them.
两种方法:
(1)定义为一个实例方法
Note that we needed to instantiate a new PictureFileCallbacks object, since we declared our callback as an instance method.
(2)定义为一个类方法
You can declare as many callbacks as you want inside your callback classes.
这一部分,guide也是没有说详细,定义的回调类中的方法和回调声明之间肯定有着紧密联系,才能实现一一对应的。以下这句,其实也从侧面说明,类中回调方法必须是与回调声明一致。
When declared inside a class, the callback method will receive the model object as a parameter.
17 Observers
Observers are similar to callbacks, but with important differences. Whereas callbacks can pollute a model with code that isn’t directly related to its purpose, observers allow you to add the same functionality outside of a model. For example, it could be argued that a User model should not include code to send registration confirmation emails.
适用场合:
Whenever you use callbacks with code that isn’t directly related to your model, you may want to consider creating an observer instead.
17.1 Creating Observers
As with callback classes, the observer’s methods receive the observed model as a parameter.
Observers are conventionally placed inside of your app/models directory and registered in your application’s config/application.rb file.
As usual, settings in config/environments take precedence over those in config/application.rb. So, if you prefer that an observer doesn’t run in all environments, you can simply register it in a specific environment instead.
By default, Rails will simply strip “Observer” from an observer’s name to find the model it should observe. However, observers can also be used to add behaviour to more than one model, and so it’s possible to manually specify the models that our observer should observe.
- guides.rubyonrails.org 读书笔记(五)
- guides.rubyonrails.org 读书笔记(二)
- guides.rubyonrails.org 读书笔记(三)
- guides.rubyonrails.org 读书笔记(四)
- guides.rubyonrails.org 读书笔记(六)
- guides.rubyonrails.org 读书笔记(七)
- guides.rubyonrails.org 读书笔记(八)
- guides.rubyonrails.org 读书笔记(九)
- guides.rubyonrails.org 读书笔记(十): Layouts and Rendering in Rails
- http://guides.ruby-china.org/
- API Guides(五)——<Activity> To Dialogs
- RubyOnRails 小小引导(上)
- RubyOnRails 小小引导(上)
- HTML5读书笔记(五)
- 读书笔记MoreEffectiveC++(五)
- SQL读书笔记(五)
- 读书笔记(五)
- webpack学习-tree shaking(https://webpack.js.org/guides/tree-shaking/)
- 二叉树的递归与非递归遍历(Java描述)
- Windows Azure安全概述
- c# 事件
- .NET调用SAP的WebService遇到的问题
- 对象在Hibernate中的三种状态
- guides.rubyonrails.org 读书笔记(五)
- Runtime.getRuntime()
- DLL木马的原理
- Runtime.getRuntime().exec();里面产生停滞(阻塞,blocking)
- Struts2下使用FreeMarker
- 水文过程线(二)
- 如何为毛笔效果
- 基于Linux的I2C驱动组成结构
- 中国红客真相,太牛了。