Day17 心得体会&读书笔记

一、心得体会
1、今天完成了什么?

  • Rails guide 4 170页 5个小时
  • 重看了镐头书看了第一部分 1个小时

2、今天收获了什么?

  • Active Record 数据验证、严格验证。。。
  • 回调 before_create、before_save。。。
  • 关联
    • belongs_to 一对一
    • has_one 一对一
    • has_many 一对多
    • has_and_belongs_to_many 多对多
    • has_many :through 多对多
    • has_one :through 一对一

3、今天状态如何?

  • 今天状态爆表

4、今天犯了哪些错误?

  • 今天吃完饭又撸了两把王者,回来之后,看了几篇文章

5、明天还有哪些工作需要完成?

  • 明天要看镐头书的第二部分、第三部分

二、读书笔记
第三章 Active Record数据验证

本文介绍了如何使用Active Record提供的数据验证功能在数据存入数据库之前验证对象的状态。

  • 如何使用AR内建的数据验证帮助方法
  • 如何编写自定义的数据验证方法
  • 如何处理验证时产生的错误消息

2、什么时候做数据验证?
Active Record使用实例方法new_record?判断对象是否已经存入数据库。

  • create
  • create!
  • save
  • save!
  • update
  • update!

3、跳过验证

下面方法会跳过验证,不过验证是否通过都会把对象存入数据库,使用时要特别留意。

  • decrement!
  • decrement_counter
  • increment!
  • increment_counter
  • toggle!
  • touch
  • update_all
  • update_attribute
  • update_column
  • update_columns
  • update_counters

注意,使用save时如果传入validate: false,也会跳过验证,使用时要特别留意。

  • save(validate: false)

valid?和invalid?

Rails使用valid?方法检查对象是否合法。valid?方法会触发数据验证,如果对象上没有错误,就返回true,否则返回false,前面我们已经用过了:

class Person < ActiveRecord::Base
validates :name, presence: true
end

AR验证结束后,所有发现的错误都可以通过实例方法errors.message获取,该方法返回一个错误集合。如果数据验证后,这个集合为空,则说明对象是合法的。

注意,使用new方法初始化对象时,即使不合法也不会报错,因为这时还没与做数据验证。

errors[]

要检查对象的某个属性是否合法,可以使用errors[:attribute]中包含:attribute的所有错误。如果某个属性没有错误,就会返回空数组。

这个方法只在数据验证之后才能使用,因为它只是用来收集错误的,并不会触发验证。而且,和前面介绍的ActiveRecord::Base#invalid?方法不一样,因为erros[:attribute]不会验证整个对象,值检查对象的某个属性是否出错。

数据验证帮助方法

AR预先定义了很多数据验证帮助方法,可以直接在模型定义中使用,这些帮助方法提供了常用的验证规则,每次验证失败后,都会向对象的errors集合添加一个消息,这些消息和所验证的属性相关联。

每个帮助方法都可以接受任意数量的属性名,所以一行代码就能在多个属性上做同一种验证。

所有的帮助方法都可指定:on和:message选项,指定何时做验证,以及验证失败后向errors集合添加什么消息,:on选项的可选值是:create和:update。

acceptance

这个方法检查表单提交时,用户界面中的复选框是否被选中,这个功能一般用来要求用户接受程序的服务条款,阅读一些文字,等等。

class Person < ActiveRecord::Base
validates :name, acceptance: true
end

这个帮助方法的默认错误消息是“must be accepted”。

这个方法可以指定:accept选项,决定可接受什么值,默认是“1”,很容易修改。

class Person < ActiveRecord::Base
validates :name, acceptance: { accept: "yes"}
end

validates_associated

如果模型和其他模型有关联,也要验证关联的模型对象,可以使用这个方法,保存对象是,会在相关联的每个对象上调用valid?方法。

class Library < ActiveRecord::Base
has_many :books
validates_associated :books
end

这个帮助方法可用于所有关联类型。

不要在关联的两端都使用validates_associated,这样会生成一个循环。

validates_associated的默认错误消息是“is invalid”。注意,相关联的每个对象都有各自的errors集合,错误消息不会都集中在调用该方法的模型对象上。

confirmation

如果要检查两个文本字段的值是否相同,可以使用这个帮助方法,例如,确认Email地址或密码,这个帮助方法回传件一个虚拟属性。

class Library < ActiveRecord::Base
validates :email, confirmation: true
end

视图中这个写

<%= text_field :Library, :email_confirmation %>

只有email_confirmation的值不是nil时才会做这个验证。所以要确认属性加上存在性验证。

class Library < ActiveRecord::Base
validates :email, confirmation: true
validates :email_confirmation, presence: true
end

这个帮助方法的默认错误消息是“doesn't match confirmation”。

exclusion

这个帮助方法检查属性的值是否不在指定的集合中。集合可以是任何一种可枚举的对象。

class Account < ActiveRecord::Base
validates :subdomain, exclusion: { in: %w(www us ca jp), message: "%{value} is reserved."}
end

exclusion方法指定:in选项,设置哪些值不能作为属性的值,:in选项有个别名:with,作用相同,上面的例子设置了:message选项,演示如何获取属性的值。

默认的错误消息是“is reserved”

format

这个帮助方法检查属性的值是否匹配:with选项指定的正则表达式。

class Account < ActiveRecord::Base
validate :legacy_code, format: { with: /\A[a-zA-Z]+\z/, message: "only allows letters" }
end

默认的错误消息是“is invalid”。

inclusion

这个帮助方法检查属性的值是否在指定的集合中。集合可以是任何一种可枚举的对象。

class Coffee < ActiveRecord::Base
validates :size, inclusion: { in: %w(small medium large), message: "%{value} is not a valid size" }
end

inclusion方法要指定:in选项,设置可接受哪些值。:in选项有个别名:with,作用相同。上面的例子设置了:message选项,演示如何获取属性的值。

该方法的默认错误消息是“is not included in the list”。

length

这个帮助方法验证属性值的长度,有多个选项,可以使用不同的方法指定长度限制:

class Person < ActiveRecord::Base
validates :name, length: {minimum: 2}
validates :bio, lenght: {maximum: 500}
validates :password, lenght: {in: 6..20}
validates :registration_number, length: {is: 6}
end

可用的长度限制选项有:

  • :minimum: 属性的值不能比指定的长度短;
  • :maximum: 属性的值不能比指定的长度长;
  • :in (或:within):属性值的长度在指定值之间,该选项的值必须是一个范围。
  • :is:属性值的长度必须等于指定值;

默认的错误消息根据长度验证类型而有所不同,还是可以:message定制。定制消息时,可以使用:wrong_length、:too_long和:too_short选项,%{count}表示长度限制的值。

class Person < ActiveRecord::Base
validates :bio, length: {maximum: 1000, too_long: "%{count} characters is the maximum allowed"}
end

这个帮助方法默认统计字符数,但可以使用:tokenizer选项设置其他的统计方式:

numericality

这个帮助方法检查属性的值是否包含数字,默认情况下,匹配的值是可选的正负符号后加整数或浮点数,如果只接受整数,可以把:only_integer选项设为true。

/\A[+-]?\d+\Z/

否则,会尝试使用Float把值转换成数字。

presence
这个帮助方法坚持指定的属性是否为非空值,调用blank?方法检查是否为nil或空字符串。

absence

这个方法验证指定的属性是否为空,使用present?方法检测值是否为nil。

uniqueness

这个帮助方法会在保存对象之前验证属性值是否唯一。

validates_with

这个帮助方法把记录交给其他的类做验证。

validates_each

这个帮助方法会把属性值传入代码库做验证,没有预先定义验证的方式,你应该在代码库中定义验证方式。

常用的验证选项

:allow_nil

指定:allow_nil选项后,如果验证的值为nil就会跳过验证。

:allow_blank

:allow_blank选项和:allow_nil选项类似,如果验证的值为空,就会跳过验证。

:message

如果验证失败,会把:message选项指定的字符串添加到errors集合中。

:on

指定什么时候做验证。

严格验证

数据验证还可以使用严格验证模式,失败后会抛出ActiveModel::StrictValidationFailed异常。

条件验证

有时只有满足特定条件时做验证才说的通

指定Symbol

:if和:unless选项的值为Symbol时,表示要在验证之前执行对应的方法。

指定字符串
:if和:unless选项的值还可以是字符串

指定Proc

:if和:unless选项的值还可以是Proc

条件组合

有时同一个条件会用在多个验证上,这时可以使用with_options方法:

联合条件

如果是否做某个验证要满足多个条件时,可以使用数组,而且,都一个验证可以同时指定:if和:unless选项。

自定义验证方式

自定义验证使用的类

自定义验证使用的方法

还可以自定义方法验证模型的状态,如果验证失败,向errors集合添加错误信息,然后还要使用类方法validate注册这些方法。

处理验证错误

除了前面介绍的valid?和invalid?方法之外,Rails还提供了很多方法用来处理errors集合,以及查询对象的合法性。

errors[:base]

在视图中显示验证错误

Active Record 回调

  • AR对象的生命周期
  • 如何编写回调方法响应对象声明周期内发生的事件
  • 如何把常用的回调封装到特殊的类中;

对象的生命周期

在Rails程序运行过程中,对象可以被创建、更新和销毁。Active Record为对象的生命周期提供了很多钩子,让你控制程序及其数据。

回调可以在对象的状态改变之前或之后触发指定的逻辑操作。

回调简介

注册回调

这种类方法还可以接受一个代码块,如果操作可以使用一行代码表述,可以考虑使用代码块形式。

class Person < ActiveRecord::Base
validates :login, :email, presence: true

before_create do
self.name = login.capitalize if name.blank?
end
end

注册回调时可以指定只在对象生命周期的特定事件发生时执行:

一般情况下,都把回调方法定义为受保护的方法或私有方法,如果定义成公共方法,回调就可以在模型外部调用。

可用的回调

创建对象

  • before_validation
  • after_validation
  • before_save
  • around_save
  • before_create
  • around_create
  • after_create
  • after_save

更新对象

  • before_validation
  • after_validation
  • before_save
  • around_save

after_initialize和after_find

after_initialize回调在Active Record对象初始化时执行,包括直接使用new方法初始化和从数据库中读取记录,after_initialize回调不用直接重定义Active Record的initialize方法。

after_find回调在数据库中读取记录时执行,如果同时注册了after_find和after_initialize

after_touch

after_touch回调在触碰Active Record对象时执行。

可以结合belongs_to一起使用

执行回调

下面的方法会触发执行回调

  • create
  • create!

跳过回调

和数据验证一样,回调也可跳过,使用下列方法即可:

  • decrement
  • decrement_counter
  • delete
  • delete_all
  • increment
  • increment_all
  • toggle
  • touch
  • update_column
  • update_columns
  • update_all

终止执行

在模型中注册回调后,回调会加入一个执行队列。

关联回调
回调能在模型关联中使用,甚至可由关联定义,假如一个用户发布了多篇文章,如果用户删除了,他发布的文章也应该删除,下面我们在post模型中注册一个after_destroy回调,应用在User模型上:

条件回调
和数据验证类似,也可以满足指定条件时再调用回调方法。条件通过:if和:unless选项指定,选项的值可以是Symbol、字符串、Proc或数组。

使用Symbol
:if和:unless选项的值为Symbol时,表示要在调用回调之前执行对应的判断方法

使用字符串

使用Proc

回调的多重条件

回调类

事物回调

Active Record 关联

  • 如何声明Active Record模型间的关联
  • 怎么理解不同的Active Record关联类型
  • 如何使用关联添加的方法

为什么要使用关联?

让代码更简洁

怎么使用关联?

  • belongs_to 一对一关系
  • has_one 一对一关系
  • has_many 一对多关系
  • has_many :through 多对多关系
  • has_one :through 关联建立两个模型之间一对一关系,这种关联表示一个模型通过第三个模型拥有另一个模型的实例,例如,每个供应商只有一个账户,而且每个账户都有一个历史账户,那么定义模型:
  • has_and_belongs_to_many

使用belongs_to还是has_one

如果想建立两个模型之间的一对一关系,可以在一个模型中声明belongs_to,然后再另一个模型中声明has_one。

使用has_many :through 还是has_and_belongs_to_many

如果需要做数据验证、回调,或者连接模型上要用到其他属性,此时就要使用has_many :through

第二种方法是使用has_many :through,但无法直接建立关联,要通过第三个模型

多态关联

关联还有一种高级用法,“多态关联”。在多态关联中,在同一个关联中,模型可以属于其他多个模型。例如,图片模型可以属于雇员模型或者产品模型,模型的定义如下:

自连接

设计数据模型时会发现,有时模型要和自己建立关联,例如,在一个数据表中保存所有雇员的信息,但要建立经理和下属之间的关系,这种情况可以使用自连接关联解决:

小技巧和注意事项

  • 缓存控制
  • 避免命名冲突
  • 更新模式
  • 控制关联的作用域
  • Bi-directional associations

1、双向关联

默认情况下,AR并不知道这个关联中两个模型之间的关系,可能导致同一对象的两个副本不同步。

为了解决这个问题,引入了:inverse_of选项,可以告知Rails两者之间的关系。

2、关联详解

belongs_to 关联详解

belongs_to关联创建一个模型与另一个模型之间的一对一关系,用数据库的行话来说,就是这个类包含了外键。如果外键在另一个类中,就应该使用has_one关联。

belongs_to 关联添加的方法

如果关联的对象存在,associate方法会返回关联对象。如果找不到关联对象,则返回nil。

belongs_to方法的选项

Rails的默认设置足够智能,能满足常见需求,但有时还是需要定制belongs_to关联的行文,定制的方法很简单,声明关联时传入选项或者使用代码块即可。

belongs_to 关联支持以下选项:

  • :autosave
  • :class_name
  • :counter_cache

belongs_to的作用域

检查关联的对象是否存在

什么时候保存对象

has_one关联详解

has_one关联添加的方法

  • association(force_reload = false)
  • association =(associate)
  • build_association
  • create_association(attributes = {})

has_one 方法的选项

has_one 的作用域

有时需要定制has_one关联使用的查询方式,定制的查询可在作用域代码块中指定。

检查关联对象是否存在

什么时候保存对象?

has_many 关联详解

has_many 关联添加的方法

声明has_many后,自动获得16个关联相关的方法:

  • collection(force_reload = false)
  • collection<<(object, ...)
  • collection.delete(object, ...)

has_many 方法的选项

作用域

has_and_belongs_to_many 关联详解

关联回调

关联回调和普通回调都差不多,只不过集合生命周期中的事件触发的。关联回调有四种:

  • before_add
  • after_add
  • before_remove
  • after_remove

关联扩展

Rails基于关联代理对象自动创建的功能是死的,但是可以通过匿名模块、新的查询方法、创建对象的方法等进行扩展。

你可能感兴趣的:(Day17 心得体会&读书笔记)