简体   繁体   中英

Displaying errors in Ruby on Rails

I have trouble displaying errors in Rails. Here is my controller

def new
    if current_user
        @edible = Edible.new 
    else 
        flash[:notice] = "You need to be signed in for this action"
        redirect_to root_path
    end
end

def create
    @edible = Edible.new(params[:edible])
    if @edible.valid? && current_user.edibles.push(@edible)
        if(params[:edible][:pickup] == "1")
            respond_to do |format|
                format.html { redirect_to new_user_edible_pick_up_adress(current_user.id, @edible.id) }
            end
        else
            respond_to do |format|
                format.html { redirect_to(user_edible_path(current_user.id, @edible.id), 
                               :success => "Product saved")
                             }
            end
        end

    else
        respond_to do |format|
            format.html { redirect_to(new_user_edible_path(current_user.id,
                :alert => "Error happend" ))
            }
        end

    end

end

Form:

<%= nested_form_for @edible, :url => user_edibles_path,
    :html => { :multipart => true, :class => "signin" } do |f| %>
    <%= render 'shared/alerts', :object => @edible   %>
#standart code further...

And partial:

 <% if flash[:notice] %>
      <p class="notice"><%= flash[:notice] %></p>
    <% end %>
<% if flash[:error] %>
    <p class="error">
        <% if object %>
            <%= flash[:error] %>
            <ul>
            <% object.errors.full_messages.each do |msg| %>
                <li> <%= msg %> </li>
            <% end %>
            </ul>
        <% end %>
    </p>
<% end %>
<% if flash[:alert] %>
    <p class="alert"><%= flash[:alert] %></p>
<% end %>

I assume that @edible variable is not passed when redirecting to new page, so Rails run object.errors on new instance every time. Am I missing some obvious thing?

I assume that @edible variable is not passed when redirecting to new page

Correct. This is to be expected since the HTTP is a stateless protocol.

The trick to showing errors on your form is to render it while you have an object with errors. That means that if your model fails validations in the create action you should render instead of redirect.

def create
    @edible = Edible.new(params[:edible])
    if @edible.valid? && current_user.edibles.push(@edible)
        # No changes here
    else
        respond_to do |format|
            format.html { render :new }  # Instead of redirecting just render the form
        end

    end

end

I think that if you have a redirect after the flash[:notice] is written, then the flash will be cleared / it'll show the flash notices that apply to the root path, not the edible/new path.

as a test, maybe try:

def new
    if current_user
        @edible = Edible.new 
    else 
        flash[:notice] = "You need to be signed in for this action"
    end
end

which will leave the user on the 'new' action, and just add:

<%= flash[:notice] %>

to the 'new' action to see if the error shows up when they're not signed in.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM