tutorial rails que ejemplos curso aprender ruby-on-rails ruby ruby-on-rails-3

ruby-on-rails - que - ruby on rails tutorial



f.error_messages en Rails 3.0 (6)

Rails 3.0 ha f.error_messages y ahora requiere un complemento para que funcione correctamente. Sin embargo, quiero aprender a mostrar los mensajes de error de la (nueva) forma nativa. Estoy siguiendo la guía de introducción , que usa el método en desuso al implementar el formulario de comentarios. Por ejemplo:

<h2>Add a comment:</h2> <%= form_for([@post, @post.comments.build]) do |f| %> <%= f.error_messages %> <div class="field"> <% f.label :commenter %><br /> <%= f.text_field :commenter %> </div> <div class="field"> <%= f.label :body %><br /> <%= f.text_area :body %> </div> <div class="actions"> <%= f.submit %> </div> <% end %>

Esta es la forma correcta de hacerlo (según lo generado por el andamio):

<%= form_for(@post) do |f| %> <% if @post.errors.any? %> <div id="error_explanation"> <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 %> . . .

Entiendo que utilizo la variable @post en el último ejemplo, pero ¿a qué variable hago referencia en el primero para obtener los mensajes de error para la creación de comentarios?


Acabo de analizar los problemas de github de doralos, y han decidido eliminar los mensajes f.error en lugar de explicar cómo hacer la validación para los comentarios.


Aquí está mi solución para toda la escena de error.

Creé un parcial que simplemente usa una variable de modelo que pasaría al renderizarlo:

<%# app/views/errors/_error.html.erb %> <%= content_for :message do %> <% if model.errors.any? %> <ul> <% model.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> <% end %> <% end %>

Puede agregar fácilmente una clase html dinámica y / o nombres de identificación basados ​​en el nombre del modelo, así como en los genéricos.

Tengo las cosas configuradas donde mis mensajes de error se muestran en el mismo lugar en un archivo de diseño:

<%# app/views/layouts/application.html.erb %> <%= yield :message %>

Si uno no quiere esa funcionalidad, eliminar el content_for en el parcial sería el truco.
Entonces, en realidad, cualquier punto de vista que desee puede simplemente escribir:

<%= render ''errors/error'', model: @some_model %>

Uno podría expandir esto creando un parcial que toma una colección y aprovecha el error parcial arriba:

<%# app/views/errors/_collection.html.erb %> <% collection.each do |model| %> <%= render ''errors/error'', model: model %> <% end %>

Renderizarlo con:

<%= render ''errors/collection'', collection: @some_model.some_has_many_association %>

Me gusta de esta manera. Es simple, fácil de administrar / mantener, e increíblemente modificable.
¡Espero que esto ayude!

EDITAR: Todo en HAML

-# app/views/errors/_error.html.haml = content_for :message do - if model.errors.any? %ul - model.errors.full_messages.each do |msg| %li= msg


-# app/views/layouts/application.html.haml = yield :message


= render ''errors/error'', model: @some_model


-# app/views/errors/_collection.html.haml - collection.each do |model| = render ''errors/errors'', model: @some_model


= render ''errors/_collection'', collection: @some_model.some_has_many_association


Esta funcionalidad existe como una gema independiente dynamic_form .

Agregue lo siguiente a su Gemfile

gem ''dynamic_form''

De la dynamic_form :

DynamicForm contiene algunos métodos de ayuda para ayudarle a manejar sus modelos de Rails3, estos son:

  • input(record, method, options = {})
  • form(record, options = {})
  • error_message_on(object, method, options={})
  • error_messages_for(record, options={})

También agrega f.error_messages y f.error_message_on a los creadores de formularios.


Estoy bastante seguro de que todo lo que necesitarías hacer es consultar @post.comments

Entonces podrías hacer algo como:

<% @post.comments.each do |comment| %> <% if comment.errors.any? %> <% comment.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> <% end %> <% end %>

O simplemente saque todos los errores:

comment_errors = @post.comments.map(&:errors)

y luego recorrerlos en su lógica de visualización para generar cada uno de los errores de comentario.


La mejor y más limpia forma de implementar error_messages en su formulario es implementando error_messages en FormBuilder.

Por ejemplo, aquí está el método error_messages que implementé para mi último proyecto. Implementando su propio FormBuilder puede seguir las reglas y estilos de su diseñador web ... Aquí hay un ejemplo que mostrará la lista de errores en ul / li''s con algunos estilos personalizados:

class StandardBuilder < ActionView::Helpers::FormBuilder def error_messages return unless object.respond_to?(:errors) && object.errors.any? errors_list = "" errors_list << @template.content_tag(:span, "There are errors!", :class => "title-error") errors_list << object.errors.full_messages.map { |message| @template.content_tag(:li, message) }.join("/n") @template.content_tag(:ul, errors_list.html_safe, :class => "error-recap round-border") end end

Entonces en mis formas:

= f.error_messages

Y eso es todo.


Supongo que la [@post, @post.comments.build] acaba de pasar a polymorphic_path dentro de form_for . Esto genera una ruta de sub-recursos para comentarios (como /posts/1/comments en este caso). Entonces, parece que su primer ejemplo usa comentarios como sub-recursos para las publicaciones, ¿verdad ?.

Así que en realidad el controlador que se llamará aquí es el CommentsController . La razón por la cual la solución de Lukas no funciona para usted podría ser que en realidad no use @ post.comments.build dentro del controlador al crear el comentario (no importa que lo use en la vista cuando llame a form_for ) El método CommentsController#create debería verse así (más o menos):

def create @post = Post.find(params[:post_id] @comment = @post.comments.build(params[:comment]) if(@comment.save) # you would probably redirect to @post else # you would probably render post#show or wherever you have the form end end

Luego puede usar el código generado por el andamiaje, solo reemplace @post variable de instancia con @comment en todas las líneas, excepto form_for call.

Creo que también puede ser una buena idea agregar @comment = @post.comment.build al método del controlador que muestra este formulario y usar form_for([@post, @comment], ...) para mantener el contenido del formulario se muestra en el formulario si hay errores.

Si esto no funciona y no puede resolverlo, agregue su método CommentsController#create a la pregunta.