2012-03-25 6 views
1

ich ein Modell haben: review.rbanzeigen Verein Fehler in einer Form

class Review < ActiveRecord::Base 
    validates :title, :presence => true 
    belongs_to :product 
end 

Modell: product.rb

class Product < ActiveRecord::Base 
    validates :name, :presence => true 

    has_many :reviews, :dependent => :destroy 
end 

und diese Form: _form.html.haml

=form_for([@product, @product.reviews.build]) do |f| 
    .field 
    =f.label :title 
    %br 
    =f.text_field :title 

mit diesem reviews_controller:

def create 
    @product = Product.find(params[:product_id]) 
    @review = @product.reviews.create(params[:review]) 
    redirect_to product_path(@product) 
end 

Wenn ich eine Rezension ohne Titel hinzufüge, wird die Rezension nicht erstellt, weil der Titel erforderlich ist (was gut ist). Ich bin mir nicht sicher, wie die Fehler auf dieser Assoziation angezeigt werden.

Ich versuchte dies:

=form_for([@product, @product.reviews.build]) do |f| 
    -if @product.reviews.errors.any? 
    .errors 
     %h2 
     =pluralize(@product.reviews.errors.count, "error") 
     %ul 
     [email protected]_messages.each do |msg| 
      %li 
      =msg 

aber habe diesen Fehler:

undefined method `errors' for #<ActiveRecord::Relation:0x00000103e31df0> 

ich das versucht:

-if @review.errors.any? 
    .errors 
     %h2 
     =pluralize(@review.errors.count, "error") 
     %ul 
     [email protected]_messages.each do |msg| 
      %li 
      =msg 

Und bekam:

undefined method `errors' for nil:NilClass 

In der Steuerung, wenn ich:

#<ActiveModel::Errors:0x00000103d88c28 @base=#<Review id: nil, title: "", description: "", rating: nil, helpful: nil, product_id: 1, created_at: nil, updated_at: nil>, @messages={:title=>["can't be blank", "is too short (minimum is 5 characters)"]}> 

Was vergessen bin ich:

raise @review.errors.inspect 

ich die Fehler sehen kann? Wie bekomme ich die Fehler angezeigt?

Danke

Antwort

3

Wenn Sie den Anruf zu redirect_to product_path(@product) machen, Sie einen anderen Controller-Aktion berufen sich, nämlich die Products#show Aktion. Die Instanzvariablen Ihrer Ansichten wurden zurückgesetzt. Sie initialisieren wahrscheinlich keine @review Instanzvariable in dieser Aktion, weshalb Sie eine Ausnahme erhalten.

Was Sie wollen, ist so etwas wie dieses

# posts_controller.rb 
def show 
    @product = Product.find(params[:product_id]) 
    @review = @product.reviews.build 
end 

# show.html.erb 
= form_for([@product, @review]) do |f| 
    -if @review.errors.any? 
    .errors 
     %h2 
     =pluralize(@review.errors.count, "error") 
     %ul 
     [email protected]_messages.each do |msg| 
      %li 
      =msg 

# reviews_controller.rb 
def create 
    @product = Product.find(params[:product_id]) 
    @review = @product.reviews.build(params[:review]) 
    if @review.save 
    redirect_to product_path(@product) 
    else 
    render 'products/show' 
    end 
end 

Der Schlüssel ist, dass, wenn die review erfolglos erstellt wird, werden Sie intakt die Seite mit den gleichen Instanzvariablen neu rendern.

+0

Dies scheint das @ @ review-Modell dem @ product nicht hinzuzufügen. Ich denke nicht, dass @review nur bei @review aufrufen wird, um es bei @product zu speichern. '@product.reviews << @ review' sollte den Trick machen, nein? Gibt es etwas besseres? – AdamT

+0

Der Aufruf von '' '@ product.reviews.build (...)' '' sollte genau das tun. Insbesondere wird die Produkt-ID des @ review-Modells auf die des @ product gesetzt. –

+1

Sie können die errors-Methode nicht in der Assoziation "reviews" verwenden, die error-Methode kann nur für ein einzelnes Objekt wie @product verwendet werden. –