Computer >> Máy Tính >  >> Lập trình >> Ruby

Ruby on Rails View Patterns and Anti-pattern

Chào mừng bạn trở lại với phần thứ ba của loạt bài Ruby on Rails Patterns and Anti-Patterns. Trong các bài viết trước, chúng tôi đã đề cập đến các pattern vàanti-pattern nói chung cũng như liên quan đến Rails Models. Trong bài đăng này, chúng tôi sẽ giới thiệu cho các bạn một số mẫu và phản mẫu liên quan đến chế độ xem Rails.

Các chế độ xem Rails đôi khi có thể hoạt động hoàn hảo và nhanh chóng, và những lúc khác, chúng có thể có đủ loại vấn đề. bạn. Hãy đi sâu vào ngay.

Như bạn có thể đã biết, khung công tác Rails tuân theo quy ước về cấu hình, và vì Rails lớn về mẫu Model-View-Controller (MVC), phương châm này cũng áp dụng một cách tự nhiên cho mã View. Điều này bao gồm đánh dấu của bạn (tệp ERB hoặcSlim), tệp JavaScript và CSS. Thoạt nhìn, bạn có thể nghĩ rằng lớp View khá đơn giản và dễ dàng, nhưng hãy nhớ rằng ngày qua, có sự kết hợp của các công nghệ trong lớp View.

Chúng tôi sử dụng JavaScript, HTML và CSS trong chế độ xem. Ba điều này dẫn đến sự nhầm lẫn và vô tổ chức của mã - dẫn đến việc triển khai không có nhiều ý nghĩa về lâu dài. May mắn thay, hôm nay chúng ta sẽ xem xét một số vấn đề phổ biến và giải pháp với lớp Rails View.

Lượt xem Powerlifting

Đây là một sai lầm không thường xuyên xảy ra, nhưng khi nó xảy ra, đó là một vườn nho. Đôi khi, mọi người có xu hướng đặt logic miền hoặc truy vấn trực tiếp bên dưới Chế độ xem. Điều này làm cho lớp View thực hiện việc nâng hoặc nâng hạng nặng. Điều thú vị là Rails thực sự cho phép điều này dễ dàng xảy ra.

Theo định nghĩa, lớp View của mẫu MVC nên chứa đoạn văn bản trình bày. Nó không nên bận tâm với logic miền hoặc với dữ liệu truy vấn. Trong Rails, bạn nhận được các tệp ERB (Embedded Ruby) cho phép bạn viết codet Ruby sau đó sẽ được đánh giá thành HTML. Nếu chúng ta xem xét một ví dụ về trang web liệt kê các bài hát trên trang chỉ mục, thì logic chế độ xem sẽ nằm trong app/views/songs/index.html.erb .

Để minh họa "powerlifting" có nghĩa là gì và không nên làm gì, hãy xem ví dụ sau:

# app/views/songs/index.html.erb
 
<div class="songs">
  <% Song.where(published: true).order(:title) do |song| %>
    <section id="song_<%= song.id %>">
      <span><%= song.title %></span>
 
      <span><%= song.description %></span>
 
      <a href="<%= song.download_url %>">Download</a>
    </section>
  <% end %>
</div>

Một mô hình chống lại rất lớn ở đây là tìm nạp các bài hát ngay trong phần đánh dấu. Trách nhiệm tìm nạp dữ liệu nên được giao cho bộ điều khiển hoặc thiết bị hỗ trợ đang được gọi từ bộ điều khiển. Đôi khi tôi thấy mọi người chuẩn bị một số dữ liệu trong bộ điều khiển và sau đó tìm nạp thêm dữ liệu trong các chế độ xem. Đây là thiết kế tồi và nó làm cho trang web của bạn chậm hơn vì bạn đang áp lực cơ sở dữ liệu của mình với các truy vấn thường xuyên hơn.

Thay vào đó, điều bạn nên làm là để lộ @songs biến cá thể từ hành động của bộ điều khiển và gọi nó trong đánh dấu, như sau:

class SongsController < ApplicationController
  ...
 
  def index
    @songs = Song.all.where(published: true).order(:title)
  end
 
  ...
end
# app/views/songs/index.html.erb
 
<div class="songs">
  <% @songs.each do |song| %>
    <section id="song_<%= song.id %>">
      <span><%= song.title %></span>
 
      <span><%= song.description %></span>
 
      <a href="<%= song.download_url %>">Download</a>
    </section>
  <% end %>
</div>

Những ví dụ này không hoàn hảo. Nếu bạn muốn giữ cho bộ điều khiển codemore của mình có thể đọc được và tránh SQL Pasta, tôi khuyên bạn nên xem bài đăng trên blog trước đó. / P>

Tận dụng những gì Rails mang lại cho bạn

Chúng tôi sẽ giữ nó ngắn gọn ở đây. Ruby on Rails như một khung công tác đi kèm với rất nhiều trình trợ giúp mới, đặc biệt là bên trong chế độ xem. Những trợ giúp nhỏ tiện lợi này cho phép bạn xây dựng lớp Chế độ xem của bạn một cách nhanh chóng và dễ dàng. Là một người mới bắt đầu sử dụng Rails, bạn có thể bị cám dỗ để viết HTML đầy đủ bên trong các tệp ERb của mình như sau:

# app/views/songs/new.html.erb
 
<form action="/songs" method="post">
  <div class="field">
    <label for="song_title">Title</label>
    <input type="text" name="song[title]" id="song_title">
  </div>
 
  <div class="field">
    <label for="song_description">Description</label>
    <textarea name="song[description]" id="song_description"></textarea>
  </div>
 
  <div class="field">
    <label for="song_download_url">Download URL</label>
    <textarea name="song[download_url]" id="song_download_url"></textarea>
  </div>
 
  <input type="submit" name="commit" value="Create Song">
</form>

Với HTML này, bạn sẽ có được một biểu mẫu đẹp cho một bài hát mới như được thấy trong ảnh chụp màn hình bên dưới:

Tuy nhiên, với Rails, bạn không cần và cũng không nên viết HTML đơn giản như vậy vì Rails đã hỗ trợ bạn ngay tại đó. Bạn có thể sử dụng form_with xem người trợ giúp sẽ tạo HTML cho bạn. form_with đã được giới thiệu trong Rails 5.1 và ở đó để thay thế form_tagform_for điều đó có thể quen thuộc với một số người. Hãy xem cách form_with có thể giúp chúng tôi không phải viết thêm mã:

<%= form_with(model: song, local: true) do |form| %>
  <div class="field">
    <%= form.label :title %>
    <%= form.text_field :title %>
  </div>
 
  <div class="field">
    <%= form.label :description %>
    <%= form.text_area :description %>
  </div>
 
  <div class="field">
    <%= form.label :download_url do %>
      Download URL
    <% end %>
    <%= form.text_area :download_url %>
  </div>
 
  <%= form.submit %>
<% end %>

Bên cạnh việc tạo HTML cho chúng tôi, form_with cũng tạo ra một xác thực để ngăn chặn các cuộc tấn công CSRF. Vì vậy, trong hầu hết các trường hợp, tốt hơn hết bạn nên sử dụng những người trợ giúp được chỉ định vì chúng có thể hoạt động tốt với khung công tác Rails.

Bên cạnh form_with , nhãn label , text_areasubmit trợ giúp, có rất nhiều trình trợ giúp chế độ xem này có sẵn với Rails. Họ ở đó để làm cho cuộc sống của bạn dễ dàng hơn và bạn nên hiểu rõ hơn về họ. Một trong những "tất cả các sao" chắc chắn là link_to :

<%= link_to "Songs", songs_path %>

Cái nào sẽ tạo HTML sau:

<a href="/songs">Songs</a>

Tôi sẽ không đi vào chi tiết về từng trợ giúp, vì bài đăng này sẽ là công cụ và việc đi qua tất cả chúng không phải là một phần của chủ đề hôm nay. Tôi đề nghị bạn hướng dẫn trình trợ giúp của gothroughRails Action View và chọn những gì bạn cần cho trang web của mình.

Sử dụng lại và tổ chức mã chế độ xem

Hãy tưởng tượng về ứng dụng web hoàn hảo. Trong trường hợp sử dụng hoàn hảo, không có câu lệnh if-else, chỉ là mã thuần túy lấy dữ liệu từ bộ điều khiển và nhập nó giữa các thẻ HTML. Loại ứng dụng đó có thể tồn tại trong các giấc mơ hackathonsand, nhưng các ứng dụng trong thế giới thực có rất nhiều nhánh và điều kiện khi hiển thị các khung nhìn.

Bạn nên làm gì khi logic hiển thị các phần của trang trở nên quá phức tạp? Nơi nào bạn đi từ đó? Một câu trả lời chung có lẽ là đạt được một thư viện hoặc khung JavaScript hiện đại và xây dựng một thứ gì đó phức tạp. Tuy nhiên, vì bài viết này về Chế độ xem Rails, chúng ta hãy xem xét các tùy chọn mà chúng ta có bên trong chúng.

Người trợ giúp sau thị trường (Tùy chỉnh)

Giả sử bạn muốn hiển thị nút gọi hành động (CTA) bên dưới bài hát. Tuy nhiên, có một điểm khó khăn - một Bài hát có thể có URL tải xuống hoặc vì bất kỳ lý do gì, nó có thể bị thiếu. Chúng tôi có thể bị cám dỗ để mã một cái gì đó tương tự như sau:

app/views/songs/show.html.erb
 
...
 
<div class="song-cta">
  <% if @song.download_url %>
    <%= link_to "Download", download_url %>
  <% else %>
    <%= link_to "Subscribe to artists updates",
                artist_updates_path(@song.artist) %>
  <% end %>
</div>
 
...

Nếu chúng ta xem ví dụ trên như một logic trình bày riêng biệt, nó không có vẻ quá tệ, phải không? Tuy nhiên, nếu có nhiều bộ báo điều kiện này, thì mã sẽ trở nên khó đọc hơn. Nó cũng làm tăng khả năng xảy ra một thứ gì đó, một nơi nào đó không được hiển thị đúng cách, đặc biệt là nếu có nhiều điều kiện hơn.

Một cách để chống lại những điều này là giải nén chúng đến một người trợ giúp riêng biệt. May mắn thay, Railsp cung cấp cho chúng ta một cách để dễ dàng viết các trình trợ giúp tùy chỉnh. Trong app/helpers chúng ta có thể tạo một SongsHelper , như vậy:

module SongsHelper
  def song_cta_link
    content_tag(:div, class: 'song-cta') do
      if @song.download_url
        link_to "Download", @song.download_url
      else
        link_to "Subscribe to artists updates",
                artist_updates_path(@song.artist)
      end
    end
  end
end

Nếu chúng ta mở trang hiển thị của một bài hát, chúng ta vẫn sẽ nhận được kết quả tương tự, tuy nhiên, chúng ta có thể làm cho ví dụ này tốt hơn một chút. Trong ví dụ trên, chúng tôi đã sử dụng biến aninstance @song . Điều này có thể không khả dụng nếu chúng tôi quyết định sử dụng trình trợ giúp này tại một nơi mà @songnil . Vì vậy, để loại bỏ sự phụ thuộc bên ngoài dưới dạng một biến thể hiện, chúng ta có thể chuyển một đối số tới trình trợ giúp như sau:

module SongsHelper
  def song_cta_link(song)
    content_tag(:div, class: 'song-cta') do
      if song.download_url
        link_to "Download", song.download_url
      else
        link_to "Subscribe to artists updates",
                artist_updates_path(song.artist)
      end
    end
  end
end

Sau đó, trong chế độ xem, chúng ta có thể gọi người trợ giúp như bên dưới:

app/views/songs/show.html.erb
 
...
 
<%= song_cta_link(@song) %>
 
...

Với điều đó, chúng ta sẽ nhận được kết quả tương tự trong chế độ xem như chúng ta đã làm trước đây. Lợi ích của việc sử dụng người trợ giúp là bạn có thể viết các bài kiểm tra cho họ để đảm bảo rằng không có vi phạm nào xảy ra liên quan đến họ trong tương lai. Vấn đề là chúng được xác định rõ ràng và bạn phải đảm bảo rằng tên của người trợ giúp là duy nhất trên ứng dụng của bạn.

Nếu bạn không phải là người thích viết các trình trợ giúp tùy chỉnh Rails, bạn luôn có thể lựa chọn sử dụng mẫu View Model với đá quý TheDraper. Hoặc bạn có thể cuộn mẫu View Model của riêng mình tại đây, nó sẽ không phức tạp. Nếu bạn mới bắt đầu với ứng dụng web của mình, tôi khuyên bạn nên bắt đầu từ từ bằng cách viết các trình trợ giúp tùy chỉnh và nếu điều đó gây khó khăn, hãy chuyển sang các giải pháp khác.

KHÔ tăng lượt xem của bạn

Điều tôi thực sự thích khi bắt đầu với Rails là khả năng KHÔ dễ dàng đánh dấu của bạn mà tôi gần như không thể tin được. Rails cung cấp cho bạn khả năng tạo các phần tử - các đoạn mã có thể tái sử dụng mà bạn có thể đưa vào bất cứ đâu. Ví dụ, nếu bạn đang hiển thị các bài hát ở nhiều nơi và bạn có cùng một mã trên nhiều tệp, thì việc tạo một phần bài hát là rất hợp lý.

Giả sử bạn thể hiện bài hát của mình như hình dưới đây:

# app/views/songs/show.html.erb
 
<p id="notice"><%= notice %></p>
 
<p>
  <strong>Title:</strong>
  <%= @song.title %>
</p>
 
<p>
  <strong>Description:</strong>
  <%= @song.description %>
</p>
 
<%= song_cta_link %>
 
<%= link_to 'Edit', edit_song_path(@song) %> |
<%= link_to 'Back', songs_path %>

Tuy nhiên, bạn cũng muốn hiển thị nó trên một trang khác có cùng đánh dấu. Sau đó, bạn có thể tạo một tệp mới với tiền tố gạch dưới như app/views/songs/_song.html.erb .

# app/views/songs/_song.html.erb
 
<p>
  <strong>Title:</strong>
  <%= @song.title %>
</p>
 
<p>
  <strong>Description:</strong>
  <%= @song.description %>
</p>
 
<%= song_cta_link(@song) %>

Và sau đó bất cứ nơi nào bạn muốn bao gồm một phần bài hát, bạn chỉ cần thực hiện như sau:

...
 
<%= render "song" %>
 
...

Rails sẽ tự động tra cứu xem _song một phần tồn tại và nó sẽ tạo ra nó. Tương tự như ví dụ với trình trợ giúp tùy chỉnh, tốt nhất là chúng ta nên loại bỏ biến cá thể @song một phần của chúng tôi.

 
# app/views/songs/_song.html.erb
<p>
  <strong>Title:</strong>
  <%= song.title %>
</p>
 
<p>
  <strong>Description:</strong>
  <%= song.description %>
</p>
 
<%= song_cta_link(song) %>

Sau đó, chúng ta sẽ cần chuyển biến bài hát vào một phần, làm cho nó dễ sử dụng hơn và phù hợp để đưa vào những nơi khác.

...
 
<%= render "song", song: @song %>
 
...

Lời kết

Đó là tất cả mọi người cho bài đăng này. Để tóm tắt, chúng ta đã xem qua một vài vấn đề và mô hình phản đối mà bạn có thể bắt gặp trong lĩnh vực Chế độ xem Rails. Dưới đây là một số điểm khác biệt:

  • Tránh logic phức tạp trong giao diện người dùng (không làm cho Chế độ xem thực hiện nhiều động lực)
  • Tìm hiểu những gì Rails cung cấp cho bạn về tính năng View helpers.
  • Cấu trúc và sử dụng lại mã của bạn với trình trợ giúp và phần mềm tùy chỉnh
  • Không phụ thuộc quá nhiều vào các biến phiên bản.

Trong bài tiếp theo, chúng tôi sẽ đề cập đến các mẫu Rails Controller và những thứ chống lại các mẫu có thể trở nên khá lộn xộn. Hãy theo dõi điều đó.

Cho đến ngày tiếp theo, hãy cổ vũ!

Tái bút. Nếu bạn muốn đọc các bài đăng của Ruby Magic ngay khi chúng xuất hiện trên báo chí, hãy đăng ký bản tin Ruby Magic của chúng tôi và không bao giờ bỏ lỡ một bài đăng nào!