Hãy bắt đầu lại từ đầu.
Chúng tôi muốn đối tượng mẫu đăng ký của chúng tôi để có API giống như bất kỳ mô hình ActiveRecord khác:
// 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
Để làm điều đó, chúng tôi tạo ra các đối tượng sau đây:
class RegForm
include ActiveModel::Model
attr_accessor :company_name, :email, :password
def save
# Save Location and Account here
end
end
Bây giờ, bằng cách bao gồm ActiveModel::Model
, chúng tôi RegForm
tăng một tấn các chức năng, bao gồm hiển thị lỗi và xác nhận các thuộc tính (có, đó là không cần thiết để bao gồm ActiveModel::Validations
). Trong bước tiếp theo này, chúng tôi thêm một số kiểm chứng thực:
validates :email, :password, presence: true
Và chúng ta thay đổi save
để nó chạy những kiểm chứng thực:
def save
validate
# Save Location and Account here
end
validate
lợi nhuận true
nếu tất cả hợp lệ vượt qua và false
khác.
validate
cũng thêm errors vào @reg_form
(Tất cả các mô hình ActiveRecord có mã số errors
được điền khi xác thực không thành công). Điều này có nghĩa rằng trong giao diện chúng ta có thể làm được điều này:
@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"]
Trong khi đó, chúng tôi RegistrationsController
nên tìm một cái gì đó như thế này:
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
Chúng ta có thể thấy rõ rằng khi @reg_form.save
lợi nhuận false
, quan điểm new
được hiển thị lại.
Cuối cùng, chúng ta thay đổi save
để mô hình của chúng tôi save
cuộc gọi được gói bên trong một 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
điểm đáng chú ý:
create!
được sử dụng thay vì create
. Các transaction chỉ được cuộn lại nếu một ngoại lệ được nâng lên (mà phương pháp với một bang thường làm).
validate
is just an alias for valid?
. Để tránh tất cả những gì thụt đầu dòng, chúng tôi thay vì có thể sử dụng một người bảo vệ ở phía trên cùng của phương pháp save
:
return if invalid?
Chúng tôi có thể biến một ngoại lệ cơ sở dữ liệu (like an email uniqueness constraint) vào một lỗi bằng cách làm một cái gì đó như:
rescue ActiveRecord::RecordNotUnique
errors.add(:email, :taken)
end
Chúng ta có thể thêm một lỗi không liên quan trực tiếp với một thuộc tính bằng cách sử dụng các biểu tượng :base
:
errors.add(:base, 'Company and Email do not match')
Cảm ơn nhưng tôi không muốn hiển thị ngoại lệ, tôi muốn hiển thị lỗi xác thực từ các mô hình khác. – Blankman