Các phương pháp hiển thị cảnh báo trong rails
Bài đăng này đã không được cập nhật trong 3 năm
Xin chào các bạn, dưới đây là bài viết cho bạn nào mới bắt đầu tìm hiểu về rails và hôm nay mình sẽ giới thiệu các bạn một vài cách hiển thị errors message trong rails nhằm giúp các bạn có thể control view của mình một cách OK nhất có thể
đầu tiên mình sẽ tạo ra một App để làm mẫu
rails new app_test
cd app_test
Sau đó, chúng ta sẽ tạo một model với view để sử dụng
rails g scaffold Product name:string price:float description:text
và giờ là tạo database và kết nối server
rake db:create
rake db:migrate
rails s
OK. và giờ mình giới thiệu qua, hiện mình biết có 2 cách hiển thị lỗi trong rails
- load trực tiếp lại trang
- load thông qua JS và trong mỗi loại đều có thể 2 loại lỗi trả về
- lỗi do validates của model sẽ trả ra cho errors messages
- lỗi cảnh báo flash
và giờ chúng ta sẽ thêm một số validates vào file app/models/product.rb
class Product < ActiveRecord::Base
validates :name, presence: true, length: {maximum: 30}
validates :price, presence: true
end
OK, và giờ chúng ta sẽ đưa đến lỗi đầu tiên là 1.1 load trực tiếp lại trang và hiển thị lỗi do validates
Sau khi chạy lệnh scaffold chúng ta sẽ load link
http://localhost:3000/products/new
Cách 1: hiển thị lỗi thông qua load lại trang
chúng ta sẽ xem kết quả trước tiên
đây là lỗi được hiển thị sau khi reload lại chính trang new đó
cơ chế của nó là khi create
ở new, dữ liệu sẽ được chuyển đến action create
def create
@product = Product.new(product_params)
respond_to do |format|
if @product.save
format.html { redirect_to @product, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: @product }
else
format.html { render :new }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
và khi dữ liệu chạy qua lệnh @product.save, model sẽ kiểm tra dữ liệu và khi dữ liệu lỗi nó sẽ được lưu dưới dạng dưới đây(PS: kiểm tra byebug sau khi sử dụng lệnh @product.save bằng lệnh @product.errors)
<ActiveModel::Errors:0x007f79fd2cb888 @base=#<Product id: nil, name: "", price: nil, description: "", created_at: nil, updated_at: nil>, @messages={:name=>["can't be blank"], :price=>["can't be blank"]}>
Như vậy chúng ta đã load được ra dữ liệu lỗi và được lưu trong @product.errors.messages
và theo format thì khi có lỗi chương trình sẽ chạy lệnh
format.html { render :new }
do đó trang new sẽ được load lại cùng với biến toàn cục @product có mang theo errors messages
và tại trang new
chúng sẽ được hiển thị thông qua đoạn code dưới
<% if @product.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@product.errors.count, "error") %> prohibited this product from being saved:</h2>
<ul>
<% @product.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
Đối với flash cũng gần tương tự như message, chỉ khác nhau một chút
Ví dụ, tôi muốn hiển thị flash cảnh báo khi cài đặt lỗi và flash thông báo khi tạo mới thành công chúng ta sẽ sửa action create của controller app/controllers/products_controller.rb
def create
@product = Product.new(product_params)
respond_to do |format|
if @product.save
flash[:success] = "Create Product Success! ^_^"
format.html { redirect_to @product, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: @product }
else
flash[:success] = "Create product Fail! >.<"
format.html { render :new }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
và hiển thị ra ở ngoài view, add đoạn dưới vào vị trí trong view hiển thị, ví dụ hiển thị lỗi trong khi create product
ta add phía trên cảnh báo messages trong app/views/products/_form.html.erb
<% flash.each do |key, value| %>
<div id="error_explanation">
<div class="alert alert-#{key}">
<%= value unless value.blank? %>
</div>
</div>
<% end %>
và chúng ta có kết quả:
Cách thứ 2: hiển thị lỗi thông qua JS
và tiếp theo, chúng ta sẽ hiển thị thông qua JS, giờ chúng ta sẽ chuyển đoạn code hiển thị message vào flash vào hai file app/view/shared/_flash.html.erb
<% flash.each do |key, value| %>
<div id="error_explanation">
<div class="alert alert-#{key}">
<%= value unless value.blank? %>
</div>
</div>
<% end %>
và file app/view/shared/_message_errors.html.erb
<% if @product.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@product.errors.count, "error") %> prohibited this product from being saved:</h2>
<ul>
<% @product.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
Đồng thời chúng ta cũng xóa đi trong app/views/products/_form.html.erb
và thêm remote: true vào trong form_for của _form
<%= form_for(@product), remote: true do |f| %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :price %><br>
<%= f.text_field :price %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
tiếp theo chúng ta sẽ sửa một chút trong controller để nhận JS app/controllers/products/products_controller.rb
def create
@product = Product.new(product_params)
respond_to do |format|
if @product.save
flash[:success] = "Create Product Success! ^_^"
format.js {}
format.html { redirect_to @product, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: @product }
else
flash[:success] = "Create product Fail! >.<"
format.js {}
format.html { render :new }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
và sau đó, chúng ta sẽ tạo ra một file app/views/products/create.js.erb
<% if @product.errors.any? %>
$(".alert").remove()
$("#error_explanation").remove()
$("form").prepend(
"<%= j render "shared/message_errors" %>")
$("form").prepend(
"<%= j render "shared/flash" %>")
<% end %>
và chúng ta cũng nhận được kết quả
Kết luận
Trên đây là 2 cách giúp các bạn hiển thị lỗi errors tùy vào trường hợp bạn sử dụng, còn đối với ý kiến của tôi thì nếu OK nhất bạn nên dùng JS, vì sẽ rất thuận tiện trong trường hợp bạn sử dụng dialog
hay modal
và muốn hiển thị lỗi nhưng không muốn bị load lại trang
Rất cám ơn các bạn đã quan tâm
Thanks for reading!
All rights reserved