Bla*_*man 9 validation ruby-on-rails
我有一个注册表单模型,在注册期间接受用户输入:
class RegForm
include ActiveModel::Model
include ActiveModel::Validations
attr_accessor :company_name, :email, :password
validates_presence_of # ...
end
Run Code Online (Sandbox Code Playgroud)
在此注册过程中,我有多个需要创建的模型,我不确定如何正确显示错误消息以及如何将模型错误消息冒泡回UI.
if @reg_form.valid?
account = Account.create!(@reg_form)
else
...
Run Code Online (Sandbox Code Playgroud)
Account.create!好像:
def self.create!(reg_form)
account = Account.create_from_reg!(reg_form)
location = location.create_from_reg!(account, reg_form)
..
..
account.location = location
..
account.save!
account
end
Run Code Online (Sandbox Code Playgroud)
让我们从头开始。
我们希望我们的注册表单对象具有与任何其他 ActiveRecord 模型相同的 API:
// 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
Run Code Online (Sandbox Code Playgroud)
为此,我们创建以下对象:
class RegForm
include ActiveModel::Model
attr_accessor :company_name, :email, :password
def save
# Save Location and Account here
end
end
Run Code Online (Sandbox Code Playgroud)
现在,通过包含ActiveModel::Model,我们RegForm获得了大量功能,包括显示错误和验证属性(是的,没有必要包含ActiveModel::Validations)。在下一步中,我们添加一些验证:
validates :email, :password, presence: true
Run Code Online (Sandbox Code Playgroud)
我们进行更改save以运行这些验证:
def save
validate
# Save Location and Account here
end
Run Code Online (Sandbox Code Playgroud)
validatetrue如果所有验证都通过false则返回,否则返回。
validate还增加了错误的@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"]
Run Code Online (Sandbox Code Playgroud)
同时,我们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
Run Code Online (Sandbox Code Playgroud)
我们可以清楚地看到,当@reg_form.save返回时false,new视图被重新渲染。
最后,我们进行更改,save以便我们的模型save调用包含在事务中:
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
Run Code Online (Sandbox Code Playgroud)
值得注意的点:
create!用于代替create. 该交易是否将引发异常只回滚(它伴随着一声巨响方法通常做的)。
validate只是 的别名valid?。为了避免所有的缩进,我们可以在save方法的顶部使用一个保护:
return if invalid?
Run Code Online (Sandbox Code Playgroud)我们可以通过执行以下操作将数据库异常(如电子邮件唯一性约束)转换为错误:
rescue ActiveRecord::RecordNotUnique
errors.add(:email, :taken)
end
Run Code Online (Sandbox Code Playgroud)我们可以使用符号添加与属性不直接关联的错误:base:
errors.add(:base, 'Company and Email do not match')
Run Code Online (Sandbox Code Playgroud)