12/08/2018, 13:15

Sử dụng Cell trong Rails

Trong mô hình MVC của Rails, mối quan hệ View - Models là rất quan trọng và có thể xây dựng nó theo OOP để việc tái sử dụng các hàm logic phức tạp trở lên dễ dàng, đồng thời giảm nhẹ và tối ưu code cho Models trong các dự án lớn. Method “partial” có lẽ đã trở lên rất quen thuộc đối ...

Trong mô hình MVC của Rails, mối quan hệ View - Models là rất quan trọng và có thể xây dựng nó theo OOP để việc tái sử dụng các hàm logic phức tạp trở lên dễ dàng, đồng thời giảm nhẹ và tối ưu code cho Models trong các dự án lớn.

Method “partial” có lẽ đã trở lên rất quen thuộc đối với mỗi lập trình viên Ruby on Rails, ưu điểm của nó là có thể gộp và tái sử dụng code View nhiều lần, tuy nhiên khi cần phải thao tác với nhiều hàm logic và muốn gộp chúng lại thành một Package để sử dụng thì vấn đề trở lên rất phức tạp và không khả thi.

Cells là một lựa chọn tuyệt vời cho bạn để giải quyết vấn đề này.

Ở bài viết này chúng ta cùng tìm hiểu và sử dụng gem Cells và những ưu điểm của nó.

I - Cells là gì?

Cells là 1 gem được sử dụng để gộp cả view lẫn controller lại thành 1 package, phát huy tối đa tính đóng gói, kế thừa, kiểm thử, đặc biệt với những view có logic phức tạp, thì cells sẽ giúp code trở nên dễ đọc và dễ dàng tái sử dụng hơn.

II - Khi nào nên sử dụng Cells?

  • xử lý các logic phức tạp, tái sử dụng lại code trong View - Models
  • hiển thị popup login
  • hiển thị ranking ở side menu
  • hiển thị comment
  • ...

III - Cài đặt gem Cells vào ứng dụng Rails

Thêm vào Gemfile trong ứng dụng của bạn:

gem 'cells'

Để sử dụng bạn cần thông qua generate:

$ rails generate cell popup_login show -e haml

Gọi một package trong Cells:

= render_cell :popup_login, :show, :property => @property_name

IV - Ví dụ với Popup Login

Khi sử dụng partial :

header_sign_in.html.haml

- unless user_signed_in?
  .header
    .header__login-button
      = link_to 'login', 'javascript:void(0);'
= render partial: 'popup_login'

_popup_login.html.haml

- unless user_signed_in?
  .popup-login
    = form_for(@user, url:user_session_path) do |f|
      %dl
        %dt= f.label :email
        %dd= f.email_field :email
        %dt= f.label :password
        %dd= f.password_field :password
      = f.submit 'Login'
   :javascript
     $('.header__login-button a').click(function(){
       $('.popup-login').css({ 'display' : 'block'});
     });

Sẽ có lỗi xảy ra nếu object @user dùng trong file _popup_login.html.haml chưa được định nghĩa trong controller.

Ta có thể định nghĩa @user trong tất cả các action có gọi _popup_login, tuy nhiên một giải pháp tốt hơn là định nghĩa trong application_controller.

application_controller.rb

class ApplicationController < ActionController::Base
  before_action: :pre_load
  def pre_load
    @user = User.new unless current_user.present?
  end
end

Nhưng nếu logi phức tạp hơn như comment, ranking...thì chắc chắn code không chỉ đơn giản và ngắn gọn như vậy.

Giải pháp triệt để cho vấn đề này là ta dùng Cells :

Cấu trúc thư mục Cells sẽ như sau :

/app
/assets
/cells
/popup_login
show.html.haml
popup_login_cell.rb

Cụ thể, chức năng popup_login sẽ được viết như sau :

app/cells/popup_login_cells.rb

class PopupLoginCell < Cell::Rails
  def show
    @user = User.new unless current_user.present?
    render
  end
end

app/cells/popup_login/show.html.haml

- unless user_signed_in?
  .popup-login
    = form_for(@user, url:user_session_path) do |f|
      %dl
        %dt= f.label :email
        %dd= f.email_field :email
        %dt= f.label :password
        %dd= f.password_field :password
      = f.submit 'Login'
   :javascript
     $('.header__login-button a').click(function(){
       $('.popup-login').css({ 'display' : 'block'});
     });

Khi partial show được gọi, cells sẽ tự động gọi controller show tương ứng và thực hiện các login cần thiết.

Với cách làm này, những hàm logic sẽ chỉ được thực hiện khi gọi cells (tối ưu hơn hẳn khi dùng application_controller), và ta chỉ cần quan tâm đến việc gọi partial trong view là đủ.

0