1
votes

I have a view, where I list data, and allow users to create new records (on a partial). The problem is, the form lives under the index action, so I lose the form's data if the user input is invalid upon redirect.

I want to keep the data, so the user doesn't have to type it all over again.

Controller:

def index  
    @instance = Instance.new
end 

def create  
    w = current_user.workspaces.find_by_id(params[:"..."]
 if w.present?
  @instance =  current_user.workspaces.find_by_id( [:"..."]).instances.create(...) 
  [:info] = "Please check your email to activate your account."
      redirect_to root_url          
    else
      flash[:info] = "Please check your data" 
      redirect_to root_url
    end 
      
end

index.html.haml

= render :partial => 'partial1'

partial1.html.haml

= form_for @instance , url: {action: "create"}  do |f|

I know that 'render' keeps the form's data, but doing:

def create  
    if something   
       ...
    else
       flash[:info] = "Please check your data" 
       render :index
    end 
          
end

I get the error

First argument in form cannot contain nil or be empty

= form_for @instance , url: {action: "create"} do |f|

How can I fix it? I don't want to initialize @instance on the create action, like this

def create  
 ...
 flash[:info] = "Please check your data" 
 @instance = Instance.create
 render :index

because I would be repeating code, which is already written on the index action.


to wrap it up:

I have a complex index view which has a form partial, with a complex controller. I Can't render :index on the create action, because I would have to load all the index's instances variables. I can't create an @instance variable if the data is incorrect, since I have a nested form.

1
when we code the 'create' action, we usually build an object, in this case an Instance object, so, we would usually do something like @instance = Instance.new(params[:instance]) in you 'create' action, with that, you would already have your variable and the error when using 'render :index' would go away. - fanta
@instance = Instance.new is only instantiating @instance for the form to store user's inputs. it's not creating an object. so, in your controller you have to retrieve that info i.e params and then use Instance.create and save so, you're not repeating code. - mrvncaragay
if you want to retain the data when user's input is invalid use render index instead of redirect_to root_url - mrvncaragay
I can't use render :index, because I have a nested form, on the index action I also load a lot of selects. I would have to load them on the create action too - Gaston
then use an ajax request, return if the save was success or if there were any errors, then in your javascript code handle the return data and process it depending on what you got. - fanta

1 Answers

0
votes

I don't want to initialize @instance on the create action...

Well, you should, since you want an instance. However, you should 'initialize' one with the parameters that were filled in the form, not 'create' one. So do something like:

def create  
 ...
 flash[:info] = "Please check your data" 
 @instance = Instance.new(params[:instance])
 render :index