Daily Archives: 29/11/2016

Rails – Tạo phương thức Helper

Chúng ta đã biết các phương thức helper là các phương thức có thể được gọi trong file View (.html.erb), trong bài render chúng ta cũng biết là có một cách để “biến” một phương thức bình thường thành một phương thức controller bình thường thành một phương thức helper là khai báo trong phương thức helper_method.

Trong bài này chúng ta sẽ định nghĩa phương thức helper rõ ràng hơn.

Trong thư mục app của project, có một thư mục có tên là helpers, tất cả các lớp controller được tạo ra sẽ có một file có tên dạng <tên controller>_helper.rb nằm trong thư mục này. Ngoài ra khi tạo project thì còn có một file nữa là application_helper.rb. Đây là các file Rails tạo cho chúng ta để định nghĩa các hàm helper.

helpers

Chúng ta sẽ viết hàm ẩn thẻ <div id="cart"> nếu giỏ hàng không có sản phẩm nào.

Đầu tiên chúng ta sửa lại file application.html.erb như sau:

<!DOCTYPE html>
<html>
<head>
<title>Books Store</title> 
    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
    <%= csrf_meta_tags %>
</head>
<body id="store">
    <div id="banner">
        <%= image_tag("logo.png") %>
        <%= @page_title || "Books Store" %>
    </div>
    <div id="columns">
        <div id="side">
            <div id="cart"> 
                <%= hide_cart_if(current_cart.line_items.empty?, :id => "cart") do %>
                <%= render current_cart %> 
                <% end %>
            </div>
 
            <a href="#">Home</a><br />
            <a href="#">FAQ</a><br />
            <a href="#">News</a><br />
            <a href="#">Contact</a><br />
        </div>
        <div id="main">
            <%= yield %>
        </div>
    </div> 
</body>
</html>

Chúng ta bọc đoạn <%= render current_cart %> bằng <%= hide_cart_if() do %>...<% end %>. Chúng ta truyền vào hàm hide_cart_if 2 tham số, mục đích là để phương thức này biết giỏ hàng có trống không và nếu trống thì ẩn thẻ nào.

Tiếp theo chúng ta định nghĩa phương thức hide_cart_if trong file application_helper.rb như sau:

module ApplicationHelper
    def hide_cart_if(condition, attributes = {}, &block) 
        if condition
            attributes["style"] = "display:none"
        end
        content_tag("div", attributes, &block) 
    end
end

Tham số condition được truyền vào ở đây cho biết giỏ hàng có trống không. Tham số attributes là một danh sách các tham số khác, ở trên chúng ta truyền vào là id có giá trị "cart". Tham số &block là đoạn <%= render current_cart %>.

Nếu conditiontrue, tức là giỏ hàng đúng là trống, thì chúng ta định nghĩa thêm một phần tử trong thuộc tính attributes có khóa là style và giá trị là "display:none".

Cuối cùng chúng ta gọi phương thức content_tag(), hàm này nhận vào tên một thẻ, danh sách các thuộc tính và giá trị của tham số đó, và biến &block, hàm này sẽ bọc những gì trong &block với tên thẻ và thuộc tính. Tức là bây giờ đoạn code hiển thị giỏ hàng sẽ có dạng như thế này:

.
.
.
<div id="cart">
    <div style="display:none">
    <%= render current_cart %>
    </div>
</div>
.
.
.

Tức là không hiển thị ra nữa.

Chúng ta cũng sửa lại phương thức destroy trong lớp CartsController để khi xóa giỏ hàng thì được trỏ về trang '/' luôn, không trở lại trang /carts nữa:

class CartsController < ApplicationController
    .
    .
    .
    # DELETE /carts/1
    # DELETE /carts/1.json
    def destroy
        @cart = current_cart
        @cart.destroy
        session[:cart_id] = nil
 
        respond_to do |format|       
            format.html { redirect_to '/' }
            format.json { head :no_content } 
        end
    end
    .
    .
    .
end

Vậy là xong.