Day17 心得體會&讀書筆記

一、心得體會
1、今天完成了什么?

  • Rails guide 4 170頁 5個小時
  • 重看了鎬頭書看了第一部分 1個小時

2、今天收獲了什么?

  • Active Record 數(shù)據(jù)驗(yàn)證、嚴(yán)格驗(yàn)證。。。
  • 回調(diào) before_create、before_save。。。
  • 關(guān)聯(lián)
    • belongs_to 一對一
    • has_one 一對一
    • has_many 一對多
    • has_and_belongs_to_many 多對多
    • has_many :through 多對多
    • has_one :through 一對一

3、今天狀態(tài)如何?

  • 今天狀態(tài)爆表

4、今天犯了哪些錯誤?

  • 今天吃完飯又?jǐn)]了兩把王者,回來之后,看了幾篇文章

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

  • 明天要看鎬頭書的第二部分、第三部分

二、讀書筆記
第三章 Active Record數(shù)據(jù)驗(yàn)證

本文介紹了如何使用Active Record提供的數(shù)據(jù)驗(yàn)證功能在數(shù)據(jù)存入數(shù)據(jù)庫之前驗(yàn)證對象的狀態(tài)。

  • 如何使用AR內(nèi)建的數(shù)據(jù)驗(yàn)證幫助方法
  • 如何編寫自定義的數(shù)據(jù)驗(yàn)證方法
  • 如何處理驗(yàn)證時產(chǎn)生的錯誤消息

2、什么時候做數(shù)據(jù)驗(yàn)證?
Active Record使用實(shí)例方法new_record?判斷對象是否已經(jīng)存入數(shù)據(jù)庫。

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

3、跳過驗(yàn)證

下面方法會跳過驗(yàn)證,不過驗(yàn)證是否通過都會把對象存入數(shù)據(jù)庫,使用時要特別留意。

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

注意,使用save時如果傳入validate: false,也會跳過驗(yàn)證,使用時要特別留意。

  • save(validate: false)

valid?和invalid?

Rails使用valid?方法檢查對象是否合法。valid?方法會觸發(fā)數(shù)據(jù)驗(yàn)證,如果對象上沒有錯誤,就返回true,否則返回false,前面我們已經(jīng)用過了:

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

AR驗(yàn)證結(jié)束后,所有發(fā)現(xiàn)的錯誤都可以通過實(shí)例方法errors.message獲取,該方法返回一個錯誤集合。如果數(shù)據(jù)驗(yàn)證后,這個集合為空,則說明對象是合法的。

注意,使用new方法初始化對象時,即使不合法也不會報錯,因?yàn)檫@時還沒與做數(shù)據(jù)驗(yàn)證。

errors[]

要檢查對象的某個屬性是否合法,可以使用errors[:attribute]中包含:attribute的所有錯誤。如果某個屬性沒有錯誤,就會返回空數(shù)組。

這個方法只在數(shù)據(jù)驗(yàn)證之后才能使用,因?yàn)樗皇怯脕硎占e誤的,并不會觸發(fā)驗(yàn)證。而且,和前面介紹的ActiveRecord::Base#invalid?方法不一樣,因?yàn)閑rros[:attribute]不會驗(yàn)證整個對象,值檢查對象的某個屬性是否出錯。

數(shù)據(jù)驗(yàn)證幫助方法

AR預(yù)先定義了很多數(shù)據(jù)驗(yàn)證幫助方法,可以直接在模型定義中使用,這些幫助方法提供了常用的驗(yàn)證規(guī)則,每次驗(yàn)證失敗后,都會向?qū)ο蟮膃rrors集合添加一個消息,這些消息和所驗(yàn)證的屬性相關(guān)聯(lián)。

每個幫助方法都可以接受任意數(shù)量的屬性名,所以一行代碼就能在多個屬性上做同一種驗(yàn)證。

所有的幫助方法都可指定:on和:message選項,指定何時做驗(yàn)證,以及驗(yàn)證失敗后向errors集合添加什么消息,:on選項的可選值是:create和:update。

acceptance

這個方法檢查表單提交時,用戶界面中的復(fù)選框是否被選中,這個功能一般用來要求用戶接受程序的服務(wù)條款,閱讀一些文字,等等。

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

這個幫助方法的默認(rèn)錯誤消息是“must be accepted”。

這個方法可以指定:accept選項,決定可接受什么值,默認(rèn)是“1”,很容易修改。

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

validates_associated

如果模型和其他模型有關(guān)聯(lián),也要驗(yàn)證關(guān)聯(lián)的模型對象,可以使用這個方法,保存對象是,會在相關(guān)聯(lián)的每個對象上調(diào)用valid?方法。

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

這個幫助方法可用于所有關(guān)聯(lián)類型。

不要在關(guān)聯(lián)的兩端都使用validates_associated,這樣會生成一個循環(huán)。

validates_associated的默認(rèn)錯誤消息是“is invalid”。注意,相關(guān)聯(lián)的每個對象都有各自的errors集合,錯誤消息不會都集中在調(diào)用該方法的模型對象上。

confirmation

如果要檢查兩個文本字段的值是否相同,可以使用這個幫助方法,例如,確認(rèn)Email地址或密碼,這個幫助方法回傳件一個虛擬屬性。

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

視圖中這個寫

<%= text_field :Library, :email_confirmation %>

只有email_confirmation的值不是nil時才會做這個驗(yàn)證。所以要確認(rèn)屬性加上存在性驗(yàn)證。

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

這個幫助方法的默認(rèn)錯誤消息是“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選項,設(shè)置哪些值不能作為屬性的值,:in選項有個別名:with,作用相同,上面的例子設(shè)置了:message選項,演示如何獲取屬性的值。

默認(rèn)的錯誤消息是“is reserved”

format

這個幫助方法檢查屬性的值是否匹配:with選項指定的正則表達(dá)式。

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

默認(rèn)的錯誤消息是“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選項,設(shè)置可接受哪些值。:in選項有個別名:with,作用相同。上面的例子設(shè)置了:message選項,演示如何獲取屬性的值。

該方法的默認(rèn)錯誤消息是“is not included in the list”。

length

這個幫助方法驗(yàn)證屬性值的長度,有多個選項,可以使用不同的方法指定長度限制:

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:屬性值的長度必須等于指定值;

默認(rèn)的錯誤消息根據(jù)長度驗(yàn)證類型而有所不同,還是可以: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

這個幫助方法默認(rèn)統(tǒng)計字符數(shù),但可以使用:tokenizer選項設(shè)置其他的統(tǒng)計方式:

numericality

這個幫助方法檢查屬性的值是否包含數(shù)字,默認(rèn)情況下,匹配的值是可選的正負(fù)符號后加整數(shù)或浮點(diǎn)數(shù),如果只接受整數(shù),可以把:only_integer選項設(shè)為true。

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

否則,會嘗試使用Float把值轉(zhuǎn)換成數(shù)字。

presence
這個幫助方法堅持指定的屬性是否為非空值,調(diào)用blank?方法檢查是否為nil或空字符串。

absence

這個方法驗(yàn)證指定的屬性是否為空,使用present?方法檢測值是否為nil。

uniqueness

這個幫助方法會在保存對象之前驗(yàn)證屬性值是否唯一。

validates_with

這個幫助方法把記錄交給其他的類做驗(yàn)證。

validates_each

這個幫助方法會把屬性值傳入代碼庫做驗(yàn)證,沒有預(yù)先定義驗(yàn)證的方式,你應(yīng)該在代碼庫中定義驗(yàn)證方式。

常用的驗(yàn)證選項

:allow_nil

指定:allow_nil選項后,如果驗(yàn)證的值為nil就會跳過驗(yàn)證。

:allow_blank

:allow_blank選項和:allow_nil選項類似,如果驗(yàn)證的值為空,就會跳過驗(yàn)證。

:message

如果驗(yàn)證失敗,會把:message選項指定的字符串添加到errors集合中。

:on

指定什么時候做驗(yàn)證。

嚴(yán)格驗(yàn)證

數(shù)據(jù)驗(yàn)證還可以使用嚴(yán)格驗(yàn)證模式,失敗后會拋出ActiveModel::StrictValidationFailed異常。

條件驗(yàn)證

有時只有滿足特定條件時做驗(yàn)證才說的通

指定Symbol

:if和:unless選項的值為Symbol時,表示要在驗(yàn)證之前執(zhí)行對應(yīng)的方法。

指定字符串
:if和:unless選項的值還可以是字符串

指定Proc

:if和:unless選項的值還可以是Proc

條件組合

有時同一個條件會用在多個驗(yàn)證上,這時可以使用with_options方法:

聯(lián)合條件

如果是否做某個驗(yàn)證要滿足多個條件時,可以使用數(shù)組,而且,都一個驗(yàn)證可以同時指定:if和:unless選項。

自定義驗(yàn)證方式

自定義驗(yàn)證使用的類

自定義驗(yàn)證使用的方法

還可以自定義方法驗(yàn)證模型的狀態(tài),如果驗(yàn)證失敗,向errors集合添加錯誤信息,然后還要使用類方法validate注冊這些方法。

處理驗(yàn)證錯誤

除了前面介紹的valid?和invalid?方法之外,Rails還提供了很多方法用來處理errors集合,以及查詢對象的合法性。

errors[:base]

在視圖中顯示驗(yàn)證錯誤

Active Record 回調(diào)

  • AR對象的生命周期
  • 如何編寫回調(diào)方法響應(yīng)對象聲明周期內(nèi)發(fā)生的事件
  • 如何把常用的回調(diào)封裝到特殊的類中;

對象的生命周期

在Rails程序運(yùn)行過程中,對象可以被創(chuàng)建、更新和銷毀。Active Record為對象的生命周期提供了很多鉤子,讓你控制程序及其數(shù)據(jù)。

回調(diào)可以在對象的狀態(tài)改變之前或之后觸發(fā)指定的邏輯操作。

回調(diào)簡介

注冊回調(diào)

這種類方法還可以接受一個代碼塊,如果操作可以使用一行代碼表述,可以考慮使用代碼塊形式。

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

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

注冊回調(diào)時可以指定只在對象生命周期的特定事件發(fā)生時執(zhí)行:

一般情況下,都把回調(diào)方法定義為受保護(hù)的方法或私有方法,如果定義成公共方法,回調(diào)就可以在模型外部調(diào)用。

可用的回調(diào)

創(chuàng)建對象

  • 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回調(diào)在Active Record對象初始化時執(zhí)行,包括直接使用new方法初始化和從數(shù)據(jù)庫中讀取記錄,after_initialize回調(diào)不用直接重定義Active Record的initialize方法。

after_find回調(diào)在數(shù)據(jù)庫中讀取記錄時執(zhí)行,如果同時注冊了after_find和after_initialize

after_touch

after_touch回調(diào)在觸碰Active Record對象時執(zhí)行。

可以結(jié)合belongs_to一起使用

執(zhí)行回調(diào)

下面的方法會觸發(fā)執(zhí)行回調(diào)

  • create
  • create!

跳過回調(diào)

和數(shù)據(jù)驗(yàn)證一樣,回調(diào)也可跳過,使用下列方法即可:

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

終止執(zhí)行

在模型中注冊回調(diào)后,回調(diào)會加入一個執(zhí)行隊列。

關(guān)聯(lián)回調(diào)
回調(diào)能在模型關(guān)聯(lián)中使用,甚至可由關(guān)聯(lián)定義,假如一個用戶發(fā)布了多篇文章,如果用戶刪除了,他發(fā)布的文章也應(yīng)該刪除,下面我們在post模型中注冊一個after_destroy回調(diào),應(yīng)用在User模型上:

條件回調(diào)
和數(shù)據(jù)驗(yàn)證類似,也可以滿足指定條件時再調(diào)用回調(diào)方法。條件通過:if和:unless選項指定,選項的值可以是Symbol、字符串、Proc或數(shù)組。

使用Symbol
:if和:unless選項的值為Symbol時,表示要在調(diào)用回調(diào)之前執(zhí)行對應(yīng)的判斷方法

使用字符串

使用Proc

回調(diào)的多重條件

回調(diào)類

事物回調(diào)

Active Record 關(guān)聯(lián)

  • 如何聲明Active Record模型間的關(guān)聯(lián)
  • 怎么理解不同的Active Record關(guān)聯(lián)類型
  • 如何使用關(guān)聯(lián)添加的方法

為什么要使用關(guān)聯(lián)?

讓代碼更簡潔

怎么使用關(guān)聯(lián)?

  • belongs_to 一對一關(guān)系
  • has_one 一對一關(guān)系
  • has_many 一對多關(guān)系
  • has_many :through 多對多關(guān)系
  • has_one :through 關(guān)聯(lián)建立兩個模型之間一對一關(guān)系,這種關(guān)聯(lián)表示一個模型通過第三個模型擁有另一個模型的實(shí)例,例如,每個供應(yīng)商只有一個賬戶,而且每個賬戶都有一個歷史賬戶,那么定義模型:
  • has_and_belongs_to_many

使用belongs_to還是has_one

如果想建立兩個模型之間的一對一關(guān)系,可以在一個模型中聲明belongs_to,然后再另一個模型中聲明has_one。

使用has_many :through 還是has_and_belongs_to_many

如果需要做數(shù)據(jù)驗(yàn)證、回調(diào),或者連接模型上要用到其他屬性,此時就要使用has_many :through

第二種方法是使用has_many :through,但無法直接建立關(guān)聯(lián),要通過第三個模型

多態(tài)關(guān)聯(lián)

關(guān)聯(lián)還有一種高級用法,“多態(tài)關(guān)聯(lián)”。在多態(tài)關(guān)聯(lián)中,在同一個關(guān)聯(lián)中,模型可以屬于其他多個模型。例如,圖片模型可以屬于雇員模型或者產(chǎn)品模型,模型的定義如下:

自連接

設(shè)計數(shù)據(jù)模型時會發(fā)現(xiàn),有時模型要和自己建立關(guān)聯(lián),例如,在一個數(shù)據(jù)表中保存所有雇員的信息,但要建立經(jīng)理和下屬之間的關(guān)系,這種情況可以使用自連接關(guān)聯(lián)解決:

小技巧和注意事項

  • 緩存控制
  • 避免命名沖突
  • 更新模式
  • 控制關(guān)聯(lián)的作用域
  • Bi-directional associations

1、雙向關(guān)聯(lián)

默認(rèn)情況下,AR并不知道這個關(guān)聯(lián)中兩個模型之間的關(guān)系,可能導(dǎo)致同一對象的兩個副本不同步。

為了解決這個問題,引入了:inverse_of選項,可以告知Rails兩者之間的關(guān)系。

2、關(guān)聯(lián)詳解

belongs_to 關(guān)聯(lián)詳解

belongs_to關(guān)聯(lián)創(chuàng)建一個模型與另一個模型之間的一對一關(guān)系,用數(shù)據(jù)庫的行話來說,就是這個類包含了外鍵。如果外鍵在另一個類中,就應(yīng)該使用has_one關(guān)聯(lián)。

belongs_to 關(guān)聯(lián)添加的方法

如果關(guān)聯(lián)的對象存在,associate方法會返回關(guān)聯(lián)對象。如果找不到關(guān)聯(lián)對象,則返回nil。

belongs_to方法的選項

Rails的默認(rèn)設(shè)置足夠智能,能滿足常見需求,但有時還是需要定制belongs_to關(guān)聯(lián)的行文,定制的方法很簡單,聲明關(guān)聯(lián)時傳入選項或者使用代碼塊即可。

belongs_to 關(guān)聯(lián)支持以下選項:

  • :autosave
  • :class_name
  • :counter_cache

belongs_to的作用域

檢查關(guān)聯(lián)的對象是否存在

什么時候保存對象

has_one關(guān)聯(lián)詳解

has_one關(guān)聯(lián)添加的方法

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

has_one 方法的選項

has_one 的作用域

有時需要定制has_one關(guān)聯(lián)使用的查詢方式,定制的查詢可在作用域代碼塊中指定。

檢查關(guān)聯(lián)對象是否存在

什么時候保存對象?

has_many 關(guān)聯(lián)詳解

has_many 關(guān)聯(lián)添加的方法

聲明has_many后,自動獲得16個關(guān)聯(lián)相關(guān)的方法:

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

has_many 方法的選項

作用域

has_and_belongs_to_many 關(guān)聯(lián)詳解

關(guān)聯(lián)回調(diào)

關(guān)聯(lián)回調(diào)和普通回調(diào)都差不多,只不過集合生命周期中的事件觸發(fā)的。關(guān)聯(lián)回調(diào)有四種:

  • before_add
  • after_add
  • before_remove
  • after_remove

關(guān)聯(lián)擴(kuò)展

Rails基于關(guān)聯(lián)代理對象自動創(chuàng)建的功能是死的,但是可以通過匿名模塊、新的查詢方法、創(chuàng)建對象的方法等進(jìn)行擴(kuò)展。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 一、心得體會 1、我完成了什么? 今天主要看了Rails guides 5的Active Record的3、4、5...
    柳輝閱讀 280評論 0 0
  • 一、心得體會1、今天完成了什么? 5個小時看完了Rails-guide 4 ,遠(yuǎn)遠(yuǎn)沒有完成看一半的計劃,一個是內(nèi)容...
    柳輝閱讀 424評論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,951評論 19 139
  • 模型 一、Active Record 基礎(chǔ)介紹Models,數(shù)據(jù)庫持久性以及Active Record模式 Act...
    廖馬兒閱讀 6,564評論 0 2
  • 一、讀書筆記3.2 對象和屬性 昨天我們學(xué)到KaraokeSong是Song的子類,但是我們并沒有指定Song類本...
    柳輝閱讀 293評論 0 0