Introducción a Rails

Usando parciales para eliminar la duplicidad en las vistas

partials son lo que Rails usa para remover la duplicidad en las vistas. Aquí hay un ejemplo:

# app/views/user/show.html.erb

<h1><%= @user.name %></h1>

<%= render 'user_details' %>

# app/views/user/_user_details.html.erb

<%= @user.location %>

<%= @user.about_me %>

La plantilla users/show automáticamente incluirá el contenido de la plantilla users/_user_details. Nota que los parciales tienen como prefijo un subrayado, de manera de no confundirlas con vistas regulares. Sin embargo, no incluyas el subrayado cuando las incluyas dentro del método helper.

CONSEJO: Puedes leer más acerca de parciales en la guía Layouts and Rendering in Rails.

Nuestra acción edit parece muy similar a la acción new, en efecto ellos comparten el mismo código para mostrar el formulario. Vamos a limpiarlo usando un parcial.

Crea un nuevo archivo app/views/posts/_form.html.erb con el siguiente contenido:

<%= form_for @post do |f| %>
  <% if @post.errors.any? %>
  <div id="errorExplanation">
    <h2><%= pluralize(@post.errors.count, "error") %> prohibited
      this post from being saved:</h2>
    <ul>
    <% @post.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
  </div>
  <% end %>
  <p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </p>

  <p>
    <%= f.label :text %><br>
    <%= f.text_area :text %>
  </p>

  <p>
    <%= f.submit %>
  </p>
<% end %>

Todo, excepto la declaración form_for permanece igual. Como form_for puede averiguar la action y los atributos del method correcto cuando construye el formulario será explicado en unos momentos. Por ahora, vamos a actualizar la vista app/views/posts/new.html.erb para usar el nuevo parcial, reescribiendo completamente:

<h1>New post</h1>

<%= render 'form' %>

<%= link_to 'Back', :action => :index %>

Luego hacer lo mismo a la vista app/views/posts/edit.html.erb:

<h1>Edit post</h1>

<%= render 'form' %>

<%= link_to 'Back', :action => :index %>

Ve con tu navegador a http://localhost:3000/posts/new y trata de crear un nuevo artículo. Todo funciona todavía, ahora tratemos de editar el artículo y recibiremos el siguiente mensaje de error:

Undefined method post_path

Para entender este error necesitamos conocer cómo funciona form_for. Cuando pasas un objeto a form_for y no especificas la opción de :url, Rails trata de adivinar las opciones de action y method verificando si el objeto pasado es un nuevo registro o no. Rails sigue la convención REST, de esta manera si se está creando un nuevo objeto Post buscará por una ruta llamada post_path y para actualizar un objeto Post buscará por una ruta llamada post_path y le pasará el objeto actual. Similarmente, Rails conoce que debe crear nuevos objetos a través de POST y actualizarlos a través de PUT.

Si ejecutas rake routes desde la consola verás que ya tenemos una ruta posts_path, la cual fue creada automáticamente por Rails cuando se definió la ruta por la acción index. Sin embargo, no tenemos aún un post_path, la cual es la razón por la que recibimos el error anterior.

# rake routes

    posts GET  /posts(.:format)            posts#index
posts_new GET  /posts/new(.:format)        posts#new
          POST /posts(.:format)            posts#create
          GET  /posts/:id(.:format)        posts#show
          GET  /posts/:id/edit(.:format)   posts#edit
          PUT  /posts/:id(.:format)        posts#update
     root      /                           welcome#index

Para arreglar eso, abrimos el archivo config/routes.rb y modificamos la línea get "posts/:id" a esto:

get "posts/:id" => "posts#show", :as => :post

La opción :as le dice al método get que queremos hacer que los asistentes de ruteo llamados post_url y post_path estén disponibles para nuestra aplicación. Estos son los métodos que form_for necesita cuando estamos editando un artículo y que ahora están disponibles para actualizar los artículos.

NOTA: La opción :as esta disponible también en los métodos de ruteo post, put, delete y match.