12/08/2018, 16:31

Action view trong rails

Sau khi đọc xong bài này mọi người sẽ nắm được: Action View là gì và cách sử dụng chúng Làm thế nào để sử dụng template, particals và layouts một cách tốt nhất Các hepler được cung cấp bởi Action View Cách sử dụng localized views Trong rails, các request sẽ được handle bởi Action ...

Sau khi đọc xong bài này mọi người sẽ nắm được:

  • Action View là gì và cách sử dụng chúng
  • Làm thế nào để sử dụng template, particals và layouts một cách tốt nhất
  • Các hepler được cung cấp bởi Action View
  • Cách sử dụng localized views

Trong rails, các request sẽ được handle bởi Action Controller và Action View. Thông thường, Action controller sẽ xử lý việc thao tác với CSDL và thực hiện CRUD khi cần thiết. Action View sẽ có trách nhiệm tạo ra các response đến người dùng. Action view được viết bởi các biến Ruby nhúng trong các tag html. Để tránh lộn xộn, một số class helper cung cấp phần xử lý chung cho các forms, dates và string. Nó rất dễ dàng để có thể add một helper mới cho ứng dụng của bạn khi nó phát triển.

Tương ứng với mỗi controller sẽ có liên kết với thư mục app/views để giữ các template files làm việc được cùng với controller. Những file đó được sử dụng để hiển thị view tương ứng với từng controller action.

$ bin/rails generate scaffold article
      [...]
      invoke  scaffold_controller
      create    app/controllers/articles_controller.rb
      invoke    erb
      create      app/views/articles
      create      app/views/articles/index.html.erb
      create      app/views/articles/edit.html.erb
      create      app/views/articles/show.html.erb
      create      app/views/articles/new.html.erb
      create      app/views/articles/_form.html.erb
      [...]

Đây là name convention cho view trong rails. Thông thường, view sẽ share tên của chúng liên kết với controller action, bạn có thể xem ở bên trên. Ví dụ: index controller của articles_controller.rb sẽ sử dụng view index.html.erb trong thư mục app/views/articles. HTML được return đến client sẽ bao gồm cả sự kết hợp của erb file và layout template sẽ wrap chúng.

Templates

Action view template có thể được viết bằng nhiều cách. Nếu file template là .erb thì chúng có thể được viết cả các tags ERB và HTML. Nếu view template được viết bằng .builder thì chúng sẽ sử dụng thư viện Builder::XmlMarkup.

ERB

Với erb thì code ruby có thể được để trong tags <% %> và <%= %>. <% %> sẽ excute ruby code nhưng không return về giá trị nào cả. Trong trường hợp có các điều kiện, vòng lặp, or blocks thì sử dụng code <%= %> nếu bạn muốn output.

<h1>Names of all the people</h1>
<% @people.each do |person| %>
  Name: <%= person.name %><br>
<% end %>

Như ví dụ trên loop sẽ sử dụng tag <% %> và person.name sẽ sử dụng tag output <%= %>.

Builder

Được sử dụng đặc biệt để sinh XML. XmlMarkup object name xml sẽ được tự động tạo template với .builder extension.

Một số ví dụ

xml.em("emphasized")
xml.em { xml.b("emph & bold") }
xml.a("A Link", "href" => "http://rubyonrails.org")
xml.target("name" => "compile", "option" => "fast")

Đoạn code trên sẽ tạo ra:

<em>emphasized</em>
<em><b>emph &amp; bold</b></em>
<a href="http://rubyonrails.org">A link</a>
<target option="fast" name="compile" />

Vd2:

xml.div {
  xml.h1(@person.name)
  xml.p(@person.bio)
}

Đoạn code trên sẽ tạo ra:

<div>
  <h1>David Heinemeier Hansson</h1>
  <p>A product of Danish Design during the Winter of '79...</p>
</div>

Jbuilder

Jbuilder là 1 gem được phát triển bởi rails team và chứa trong đó là những cái default của gemfile rails. Tương tự với builder, nhưng lại được sử dụng để tạo ra JSON thay vì XML. Dưới đây là ví dụ đơn giản:

json.name("Alex")
json.email("alex@example.com")

Đoạn code trên sẽ tạo ra

{
  "name": "Alex",
  "email": "alex@example.com"
}

Partials

Partial templates thường được gọi là partical, bạn có thể tách từng phần của code từ template thành riêng biệt và sử dụng lại chúng thông qua template của bạn

Naming Partials

Để render từng phần của code ra view, sử dụng render method

<%= render "menu" %>
<%= render "shared/menu" %>

Code này sẽ được lấy một phần từ app/views/shared/_menu.html.erb.

Sử dụng particals để đơn giản hóa views

<%= render "shared/ad_banner" %>
 
<h1>Products</h1>
 
<p>Here are a few of our fine products:</p>
<% @products.each do |product| %>
  <%= render partial: "product", locals: { product: product } %>
<% end %>
 
<%= render "shared/footer" %>

Ở đây, phần adbanner.html.erb và footer.html.erb có thể chứa được nội dung có thể sử dụng ở nhiều page trong application của bạn. Bạn không cần phải xem chi tiết của từng sections khi bạn đang ở 1 trang cụ thể

Render mà không cần partial locals options

Như ở 2 ví dụ trên, render sẽ có 2 options: partial và locals. Nhưng bạn vẫn có thể skip chúng bằng ví dụ dưới đây Thay vì

<%= render partial: "product", locals: { product: @product } %>

Thì có thể viết

<%= render "product", product: @product %>

Partial Layouts

Bây giờ chúng ta đang hiển thị nội dung trên page được wrap bởi tag div. Đầu tiên, chúng ta sẽ tạo Article

Article.create(body: 'Partial Layouts are cool!')

Trong show template, chúng ta sẽ render phần _article wrap trong layout articles/show.html.erb

<%= render partial: 'article', layout: 'box', locals: { article: @article } %>

Phần này sẽ wrap article trong thẻ div một cách đơn giản

<div class='box'>
  <%= yield %>
</div>

Nhưng nên chú ý rằng, một phần của layout này sẽ access đến biến local article vào pass thông qua render call. Tuy nhiên, không giống với application-wide layout. Bạn vẫn có thể render block of code trong partical layout thay vì gọi yield. Trong ví dụ bên dưới, nếu chúng ta không có article, chúng ta có thể làm điều này thay vì

<% render(layout: 'box', locals: { article: @article }) do %>
  <div>
    <p><%= article.body %></p>
  </div>
<% end %>

View Paths

Khi render sponse, controller cần phải giải quyết được là những phần view khác nhau được đặt ở đâu. Mặc định là chỉ lấy ở app/views. Chúng ta vẫn có thể add thêm các vị trí khác và đưa ra ưu tiên nhất định bằng việc sử dụng method prependviewpathappendviewpath

Prepend view path

Nó sẽ có ích khi bạn muốn put view bên trong một thư mục khác cho subdomains.

prepend_view_path "app/views/#{request.subdomain}"

Sau đó Action view sẽ tìm trong thư mục đó trước và show view.

Append view path

append_view_path "app/views/direct"

Nó sẽ add app/views/direct đến phần cuối của lookup paths.

Localized Views

0