Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

After validation fails and a form redirects back to itself, why are instance variables empty?

In a Rails 3.2 app, when a certain form fails to save (validation fails) and redirects back to the form I get an error:

undefined method `map' for nil:NilClass

This form does not display any errors when navigating directly to the new or edit paths.

The error is coming from a select field with a custom options_from_collection_for_select method.

<%= f.select(:user_ids, options_from_collection_for_select_with_attributes(@users, :id, :name, 'data-attributes', :attributes ), {include_blank:true}, {multiple:true}) %>

If I replace the instance variable @users with User.all then I don't get an error after redirect.

I guess @users is empty after the redirect, hence the error. But why? @users is defined in the new and edit controllers.

My controller is:

def create
  --bunch of stuff
  if @model.save
    --bunch of stuff
    respond_to do |format|
      format.html { render :text => model_url(@model) }
      format.html { redirect_to(@model, :notice => 'Success!.') }
      format.xml  { render :xml => @model, :status => :created, :location => @model }
    end

  else
    respond_to do |format|
      format.html { render :action => "new" }
      format.xml  { render :xml => @model.errors, :status => :unprocessable_entity }
    end
  end
end
like image 661
Andy Harvey Avatar asked Dec 04 '22 16:12

Andy Harvey


1 Answers

It's because you don't actually execute the "new" action if it fails. Here's a typical controller structure

class PotsController < ApplicationController

  def new
    @pot = Pot.new
    @users = User.all
  end

  def create
    @pot = Pot.new(params[:pot])
    if @pot.create
      redirect_to @pot, notice: "Created"
    else
      #****you are here****
      render :new
    end
  end
end

In the above, if pot.create fails, it just renders the new template. What you should do is get your instance variables in that case too

  def create
    @pot = Pot.new(params[:pot])
    if @pot.create
      redirect_to @pot, notice: "Created"
    else
      @users = User.all #this is the important line
      render :new
    end
  end
like image 50
Jesse Wolgamott Avatar answered Apr 05 '23 22:04

Jesse Wolgamott