在表单中显示关联错误

时间:2021-07-02 20:20:31

I have a model: review.rb

我有一个模型:review.rb

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

model: product.rb

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

  has_many :reviews, :dependent => :destroy
end

and this form: _form.html.haml

和这个形式:_form.html.haml

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

with this reviews_controller:

有了这个reviews_controller:

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

When I add a review with no title the review doesn't get created because the title is required (which is good). I'm not sure how to get the errors to show on this association though.

当我添加一个没有标题的评论时,评论不会被创建,因为标题是必需的(这很好)。我不知道如何在这个关联中显示错误。

I tried this:

我试过这个:

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

but got this error:

但得到了这个错误:

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

I tried this:

我试过这个:

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

And got:

undefined method `errors' for nil:NilClass

In the controller when I:

我在控制器中:

    raise @review.errors.inspect

I can see the errors:

我可以看到错误:

#<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)"]}>

What am I forgetting? How do I get the errors to show?

我忘记了什么?如何显示错误?

Thank you

1 个解决方案

#1


3  

When you make the call to redirect_to product_path(@product), you are invoking a different controller action, namely the Products#show action. The instance variables your views will have been reset. You probably aren't initializing a @review instance variable in this action which is why you are getting an exception.

当您调用redirect_to product_path(@product)时,您正在调用不同的控制器操作,即Products#show action。您的视图将被重置的实例变量。您可能没有在此操作中初始化@review实例变量,这就是您获得异常的原因。

What you want is something like this

你想要的是这样的

# 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
        =@review.errors.full_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

The key is that if the review is unsuccessfully created, you will re-render the page with the same instance variables intact.

关键是如果审核未成功创建,您将重新呈现具有相同实例变量的页面。

#1


3  

When you make the call to redirect_to product_path(@product), you are invoking a different controller action, namely the Products#show action. The instance variables your views will have been reset. You probably aren't initializing a @review instance variable in this action which is why you are getting an exception.

当您调用redirect_to product_path(@product)时,您正在调用不同的控制器操作,即Products#show action。您的视图将被重置的实例变量。您可能没有在此操作中初始化@review实例变量,这就是您获得异常的原因。

What you want is something like this

你想要的是这样的

# 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
        =@review.errors.full_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

The key is that if the review is unsuccessfully created, you will re-render the page with the same instance variables intact.

关键是如果审核未成功创建,您将重新呈现具有相同实例变量的页面。