2010-10-06 7 views
41

Rails 3.0 deprecato f.error_messages e ora richiede un plug-in per funzionare correttamente - Tuttavia, voglio imparare come visualizzare i messaggi di errore (nuovo) modo nativo. Sto seguendo lo getting started guide, che usa il metodo deprecato quando implementa il modulo dei commenti. Ad esempio:f.error_messages in Rails 3.0

<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 %> 

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

<%= 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 %> 
. . . 

comprendo che uso la variabile @post nel secondo esempio, ma ciò variabile fanno Mi riferisco al primo per ottenere i messaggi di errore per la creazione di commenti?

+0

La tua domanda è in contraddizione. Qui stai chiedendo come ottenere i messaggi di errore per i commenti "nel precedente" esempio, che indica che stai chiedendo del caso con 'f.error_messages'. (O intendevi "nella forma", non "nella prima"?) Tuttavia, nel commento, stai chiedendo come ottenere i messaggi di errore "senza usare' f.error_messages' ". Quindi qual è? –

risposta

0

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

13

Sono abbastanza sicuro che tutto quello che avresti bisogno di fare è di riferimento @post.comments

Così si potrebbe fare qualcosa di simile:

<% @post.comments.each do |comment| %> 
    <% if comment.errors.any? %> 

    <% comment.errors.full_messages.each do |msg| %> 
     <li><%= msg %></li> 
    <% end %> 

    <% end %> 
<% end %> 

O semplicemente tirare tutti gli errori out out:

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

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

+1

Grazie per il tentativo, ma no, non funziona. Forse un modo più semplice per porre la domanda sarebbe "Come posso visualizzare gli errori di commento senza usare" f.error_messages "dato" [@post, @ post.comments.build] "invece di qualcosa di semplice come @post? –

+1

onestamente, I Non ho mai visto qualcuno come 'form_for ([@ post, @ post.comments.build]). Piuttosto è sempre stato' form_for (@post) do | p | 'e poi' p.fields_for (@ post.comments. build) do | c | '. Invece puoi usare i campi per l'interno del modulo postale? – Lukas

+0

Beh, in realtà è come fa la guida" Rails - Getting started " – shadowhorst

1

Immagino che l'array [@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 quando crei il commento (non importa se lo usi nella vista quando chiami form_for). Il metodo CommentsController#create dovrebbe assomigliare a questa (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 è possibile utilizzare il codice generato da impalcature, solo sostituire @post variabile di istanza con @comment in tutte le linee ad eccezione form_for chiamata.

Penso che potrebbe anche essere una buona idea aggiungere il @comment = @post.comment.build al metodo controller che visualizza questo modulo e utilizzare form_for([@post, @comment], ...) per mantenere il contenuto del modulo visualizzato nel modulo in caso di errori.

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

22

Il modo migliore e pulito per implementare messaggi_errore nel modulo è l'implementazione di messaggi_errore in un oggetto 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 sarà in uscita la lista errori in ul/li di 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 

Poi nelle mie forme:

= f.error_messages 

E questo è tutto.

+0

Ciao Nicolas, dovrei aggiungere questo FormBuilder? –

+0

in app/helpers ... –

+0

Ancora non funziona per me. Ho tagliato e incollato il codice in un nuovo file, app/helper/standard_builder.rb, ma <% = f.error_messages%> sul mio modulo dà l'errore "metodo non definito' error_messages 'per # ". Devo fare qualcos'altro per renderlo disponibile? – digitig

7

Questa funzionalità esiste come gemma indipendente dynamic_form.

Aggiungere il seguente al vostro Gemfile

gem 'dynamic_form' 

Dal github page:

DynamicForm detiene un metodo alcuni aiutanti per aiutarvi a trattare con i vostri modelli Rails3, essi sono:

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

Si aggiunge anche f.error_messages e f.error_message_on ai vostri costruttori di forma.

3

Ecco la mia soluzione all'intera scena di errore.

ho creato un parziale che utilizza semplicemente una variabile modello che si potrebbe passare durante il rendering è:

<%# 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 %> 

È possibile aggiungere facilmente classe HTML dinamico e/o nomi di id in base al nome del modello, come così come quelli generici.

ho cose di configurazione in cui i miei messaggi di errore rendono in tutto nello stesso posto in un file di layout:

<%# app/views/layouts/application.html.erb %> 

<%= yield :message %> 

Se non si voleva che la funzionalità, la rimozione del content_for nel parziale farebbe il trucco.
Poi in realtà qualsiasi visualizzazione che si desidera si può semplicemente scrivere:

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

Uno potrebbe ulteriormente espandere questa creando un parziale 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 questo 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