f.error_messages in Rails 3.0

Rails 3.0 deprecato f.error_messages e ora richiede un plug-in per funzionare correttamente – Voglio tuttavia imparare come visualizzare i messaggi di errore (nuovo) modo nativo. Sto seguendo la guida introduttiva , che utilizza il metodo deprecato quando si implementa il modulo dei commenti. Per esempio:

 

Add a comment:



Ecco il modo corretto di farlo (come generato dallo scaffold):

   

prohibited this post from being saved:

. . .

Capisco che io uso la variabile @post nel secondo esempio, ma quale variabile faccio riferimento nel primo per ottenere i messaggi di errore per la creazione di commenti?

Ho appena esaminato i problemi github di docrails e hanno deciso di rimuovere f.error_messages invece di spiegare come convalidare i commenti.

Il modo migliore e pulito per implementare messaggi_errore nel modulo è implementando messaggi_errore in un modulo formBuilder.

Ad esempio, ecco il metodo error_messages che ho implementato per il mio ultimo progetto. Implicando il tuo FormBuilder puoi seguire le regole e gli stili del tuo webdesigner … Ecco un esempio che mostrerà l’elenco degli errori in ul / li con alcuni stili personalizzati:

 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 

Quindi nelle mie forms:

 = f.error_messages 

E questo è tutto.

Sono abbastanza sicuro che tutto ciò che dovresti fare è fare riferimento a @post.comments

Quindi potresti fare qualcosa come:

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

    O semplicemente estrai tutti gli errori:

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

    quindi esegui un ciclo attraverso di essi nella logica di visualizzazione per visualizzare ciascuno degli errori di commento.

    Questa funzionalità esiste come gem indipendente dynamic_form .

    Aggiungi il seguente al tuo Gemfile

     gem 'dynamic_form' 

    Dalla pagina github :

    DynamicForm contiene alcuni metodi di aiuto per aiutarti a gestire i tuoi modelli Rails3, sono:

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

    Aggiunge anche f.error_messages e f.error_message_on ai costruttori di moduli.

    Ecco la mia soluzione all’intera scena degli errori.

    Ho creato un partial che utilizza semplicemente una variabile del modello che si dovrebbe passare al momento del rendering:

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

    È ansible aggiungere facilmente nomi di classi e / o ID dinamici in base al nome del modello e a quelli generici.

    Ho le cose in cui i miei messaggi di errore vengono visualizzati nello stesso posto in un file di layout:

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

    Se uno non volesse quella funzionalità, rimuovere il content_for nel parziale farebbe il trucco.
    Quindi, in qualsiasi vista tu voglia, puoi semplicemente scrivere:

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

    Si potrebbe ulteriormente espandere questo creando un partial che prende una raccolta e sfrutta l’errore parziale sopra:

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

    Renderlo con:

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

    Mi piace in questo modo. È semplice, facile da gestire / mantenere e incredibilmente modificabile.
    Spero che aiuti!

    EDIT: tutto in 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 

    Immagino che l’ [@post, @post.comments.build] sia passato a polymorphic_path all’interno di form_for . Questo genera un percorso di sotto-risorsa per i commenti (come /posts/1/comments in questo caso). Quindi sembra che il tuo primo esempio usi i commenti come sotto-risorse per i post, giusto?

    Quindi in realtà il controller che verrà chiamato qui è il CommentsController . Il motivo per cui la soluzione di Lukas non funziona per te potrebbe essere che in realtà non usi @ post.comments.build all’interno del controller durante la creazione del commento (non importa che lo si usi nella vista quando si chiama form_for ). Il metodo di CommentsController#create dovrebbe apparire come questo (più o meno):

     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 

    Quindi è ansible utilizzare il codice generato dallo scaffolding, sostituire solo la variabile di istanza @comment con @comment in tutte le righe tranne form_for call.

    Penso che potrebbe essere una buona idea aggiungere il @comment = @post.comment.build al metodo controller che visualizza questo modulo e usare form_for([@post, @comment], ...) per mantenere il contenuto del modulo visualizzato nel modulo se ci sono errori.

    Se questo non funziona e non sei in grado di capirlo, aggiungi il tuo CommentsController#create metodo per la domanda.