[Rails] Cách sử dụng cells để tối ưu code
Link gốc : Việt on Rails Khi làm việc với view của Rails, không ngày nào mà không sử dụng tới method partial. Tuy nhiên, partial chỉ là 1 tính năng để gộp và tái sử dụng code view nhiều lần mà thôi. Khi muốn gộp chung cả logic vào để tạo ra template thì vấn đề sẽ rất phức tạp. Khi gặp vấn đề ...
Link gốc : Việt on Rails
Khi làm việc với view của Rails, không ngày nào mà không sử dụng tới method partial. Tuy nhiên, partial chỉ là 1 tính năng để gộp và tái sử dụng code view nhiều lần mà thôi. Khi muốn gộp chung cả logic vào để tạo ra template thì vấn đề sẽ rất phức tạp.
Khi gặp vấn đề này, cells sẽ phát huy tối đa sức mạnh của mình.
cells là 1 gem được sử dụng để gộp cả view lẫn controller lại thành 1 package, 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.
- hiển thị popup login
- hiển thị ranking ở side menu
- ...
Ví dụ với popup login
Khi sử dụng partial, ta thường viết như sau :
- 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'}); });
Vấn đề của cách viết này là trong _popup_login.html.haml có sử dụng @user, và @user này được tạo ra ở đâu. Nếu trong controller không định nghĩa @user thì đoạn code trên chắc chắn bị lỗi.
Có 2 cách giải quyết ở đây :
- định nghĩa @user ở trong tất cả các action có gọi popup_login.
- viết trong application controller
Các viết trong application_controller
Viết 1 cách đơn giản như sau :
class ApplicationController < ActionController::Base before_action: :pre_load def pre_load @user = User.new unless current_user.present? end end
Lần này chỉ là popup_login, nên logic còn khá đơn giản. Nếu mọi thứ phức tạp hơn như ranking, comment, ... thì code chắc chắn sẽ không ngắn gọn và dễ hiểu như thế.
Viết bằng cells
dashboard.html.haml
= render_cell :popup_login, :show
Login
Cấu trúc thư mục của cells sẽ như sau :
/app /assets /cells /popup_login show.html.haml popup_login_cell.rb
Các đoạn mã để thực hiện chức năng popup sẽ như sau :
app/cells/popup_login_cell.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'}); });
Thêm vào Gemfile
gem 'cells'
cells được cung cấp thông qua generate :
rails generate cell popup_login show -e haml create app/cells/ create app/cells/popup_login create app/cells/popup_login_cell.rb create app/cells/popup_login/show.html.haml create test/cells/popup_login_cell.rb
Khi gọi 1 package trong cells :
= render_cell :popup_login, :show, :property => @property_name # có thể truyền tham số cho các package của cells