diasks2
diasks2

Reputation: 2142

Ruby on Rails - continually looping through the new/create action with AJAX

I have a Rails controller set up that when a user creates a new record, it will redirect again to the new action and populate the form with new data, and this can continue on in a loop, creating a new record and getting redirected to the new action. What I am having trouble with is adding AJAX to this so that the user can stay in this loop without the page reloading. Here is my code without AJAX:

class ResponsesController
 def new
   @response = Response.new
   @answer_a = Answer.find(rand(1..100))
   @answer_b = Answer.find(rand(1..100))
   @answer_c = Answer.find(rand(1..100))
 end

 def create
   @response = current_user.responses.build(params[:response])
   if @response.save
      respond_to do |format|
        format.html { redirect_to new_response_path }
        format.js
      end
   else
      render 'new'
   end
 end
end

new.html.erb

 <div id="response_form">
   <%= render 'form' %>
 </div>

_form.html.erb

 <%= form_for @response do |f| %>   
    <%= f.radio_button :user_answer, @answer_a.id %> 
    <%= @answer_a.description %>
    <%= f.radio_button :user_answer, @answer_b.id %> 
    <%= @answer_b.description %>
    <%= f.radio_button :user_answer, @answer_c.id %> 
    <%= @answer_c.description %>
    <%= f.submit "Answer" %>                
 <% end %>

Below is my attempt to add AJAX. However, it is going to the show action and doing an update. How can I fix my code so that it keeps redirecting to the new action and the user can continue to create new records on an infinite loop?

 def create
   @answer_a = Answer.find(rand(1..100))
   @answer_b = Answer.find(rand(1..100))
   @answer_c = Answer.find(rand(1..100))
   @response = current_user.responses.build(params[:response])
   if @response.save
      respond_to do |format|
        format.html { redirect_to new_response_path }
        format.js
      end
   else
      render 'new'
   end
 end

_form.html.erb

 <%= form_for @response, :remote => true do |f| %>  
    <%= f.radio_button :user_answer, @answer_a.id %> 
    <%= @answer_a.description %>
    <%= f.radio_button :user_answer, @answer_b.id %> 
    <%= @answer_b.description %>
    <%= f.radio_button :user_answer, @answer_c.id %> 
    <%= @answer_c.description %>
    <%= f.submit "Answer" %>                
 <% end %>

create.js.erb

 $('#response_form').html('<%= j render("form") %>');

Upvotes: 0

Views: 1212

Answers (1)

Ashitaka
Ashitaka

Reputation: 19203

The code seems fine by me. It shouldn't be redirecting to the show action. Make sure that:

  1. You have gem 'jquery-rails' in your Gemfile

  2. You have <%= javascript_include_tag 'application' %> in your application.html.erb file

  3. You have the following lines in your application.js file

    //= require jquery
    //= require jquery_ujs
    

Ok, so the problem here is that you are including the line <%= form_for @response do |f| %> inside the _form partial. Why is that a problem? Well, when an object @response does not exist, Rails renders the form like this:

<form accept-charset="UTF-8" action="/responses" method="post">

When an object @response does exist, Rails renders the form like this:

<form accept-charset="UTF-8" action="/responses/id_of_the_response" method="post">

Rails does this because it knows that @response exists so it's only logical that you want to update it (and not create it again).

The solution here is to change the form_for to this:

<%= form_for @response, :url => { :action => :create, :method => :post } do |f| %>

Also, be mindful that build is not saving the @response object.

Upvotes: 3

Related Questions