讓我們從頭開始。
我們希望我們的註冊表單對象具有相同的API與任何其他的ActiveRecord模型:
// view.html
<%= form_for(@book) do |f| %>
<% end %>
# controller.rb
def create
@book = Book.new(book_params)
if @book.save
redirect_to @book, notice: 'Book was successfully created.'
else
render :new
end
end
爲了做到這一點,我們創建了以下對象:
class RegForm
include ActiveModel::Model
attr_accessor :company_name, :email, :password
def save
# Save Location and Account here
end
end
現在,包括ActiveModel::Model
,我們的RegForm
獲得了大量的功能,包括顯示錯誤和驗證屬性(是的,沒有必要包含ActiveModel::Validations
)。在這一步我們添加一些驗證:
validates :email, :password, presence: true
我們改變save
使其運行的驗證:
def save
validate
# Save Location and Account here
end
validate
回報true
如果所有驗證通過,否則false
。
validate
還增加了errors到@reg_form
(所有ActiveRecord的型號有errors
哈希當驗證失敗被填充)。這意味着,在視圖中我們可以做這些:
@reg_form.errors.messages
#=> { email: ["can't be blank"], password: ["can't be blank"] }
@reg_form.errors.full_messages
#=> ["Email can't be blank", "Password can't be blank"]
@reg_form.errors[:email]
#=> ["can't be blank"]
@reg_form.errors.full_messages_for(:email)
#=> ["Email can't be blank"]
同時,我們RegistrationsController
應該是這個樣子:
def create
@reg_form = RegForm.new(reg_params)
if @reg_form.save
redirect_to @reg_form, notice: 'Registration was successful'
else
render :new
end
end
我們可以清楚地看到,當@reg_form.save
回報false
,該new
視圖被重新渲染。
最後,我們改變save
使我們的模型save
調用一個包裹裏面transaction:
def save
if valid?
ActiveRecord::Base.transaction do
location = Location.create!(location_params)
account = location.create_account!(account_params)
end
true
end
rescue ActiveRecord::StatementInvalid => e
# Handle database exceptions not covered by validations.
# e.message and e.cause.message can help you figure out what happened
end
點值得注意:
create!
代替create
。 transaction只有在引發異常時纔會回滾(通常使用哪種方法)。
validate
is just an alias for valid?
。通過執行類似
return if invalid?
我們可以把數據庫異常(like an email uniqueness constraint)到一個錯誤:
rescue ActiveRecord::RecordNotUnique
errors.add(:email, :taken)
end
爲了避免所有的壓痕,我們反而可以使用一個守在
save
方法的頂部
errors.add(:base, 'Company and Email do not match')
:
我們可以用符號:base
添加不直接與屬性相關聯的錯誤
謝謝,但我不想顯示異常,我想顯示來自其他模型的驗證錯誤。 – Blankman