RJS Dynamic update ActionView::Template::Error (undefined method `each' for nil:NilClass)

166 Views Asked by At

I am using Rails 4.2.6/PostgreSQL and trying to make dynamic update in index that has form and generate by scaffold. I think I am doing right but having issue with render partial via rjs. Bellow is an error and code. Any idea? Or RJS still available in Rails 4??

Server

Started POST "/users" for 127.0.0.1 at 2016-06-21 18:50:59 -0700
Processing by UsersController#create as JS
  Parameters: {"utf8"=>"✓", "user"=>{"name"=>"Tim"}, "commit"=>"Create User"}
   (0.3ms)  BEGIN
  SQL (0.9ms)  INSERT INTO "users" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING     "id"  [["name", "Tim"], ["created_at", "2016-06-22 01:50:59.194072"], ["updated_at", "2016-06-22     01:50:59.194072"]]
   (63.8ms)  COMMIT
  Rendered users/_user.html.erb (37.6ms)
  Rendered users/create.js.erb (42.8ms)
Completed 500 Internal Server Error in 145ms (ActiveRecord: 65.4ms)

ActionView::Template::Error (undefined method `each' for nil:NilClass):
    1:     <% @users.each do |user| %>
    2:       <tr>
    3:         <td><%= user.name %></td>
    4:         <td><%= link_to 'Show', user %></td>
  app/views/users/_user.html.erb:1:in     `_app_views_users__user_html_erb___2381841639716957386_70119033868960'
  app/views/users/create.js.erb:1:in `_app_views_users_create_js_erb__1865303298608397742_70119034321000'
  app/controllers/users_controller.rb:30:in `create'

create.js.erb

$("#users").append("<%= escape_javascript(render @user) %>");

users_controller.rb

class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]

  # GET /users
  # GET /users.json
  def index
    @users = User.all
    @user = User.new
  end

  # GET /users/1
  # GET /users/1.json
  def show
  end

  # GET /users/new
  def new
    @user = User.new
  end

  # GET /users/1/edit
  def edit
  end

  # POST /users
  # POST /users.json
  def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: 'User was successfully created.' }
        format.json { render :show, status: :created, location: @user }
        format.js
      else
        format.html { render :new }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /users/1
  # PATCH/PUT /users/1.json
  def update
    respond_to do |format|
      if @user.update(user_params)
        format.html { redirect_to @user, notice: 'User was successfully updated.' }
        format.json { render :show, status: :ok, location: @user }
      else
        format.html { render :edit }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /users/1
  # DELETE /users/1.json
  def destroy
    @user.destroy
    respond_to do |format|
      format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_user
      @user = User.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def user_params
      params.require(:user).permit(:name)
    end
end

app/views/users/index.html

<p id="notice"><%= notice %></p>

<h1>Listing Users</h1>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody id="users">
  <%= render @user %>
  </tbody>
</table>

<br>

<%= render 'form' %>

app/views/users/_form.html.erb

<%= form_for(@user, remote: true) do |f| %>
  <% if @user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>

      <ul>
      <% @user.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

If I put something like @users = User.all in create action, it will renders all users twice as you can see in below image. enter image description here

1

There are 1 best solutions below

0
AudioBubble On

After tries and errors, I have confirmed there is an answer in Rajesh's comments. It was bit unclear in the process of tries but here is how I figure this out.

create.js.erb

Before

$("#users").append("<%= escape_javascript(render @user) %>");

After

$("#users").html("<%= escape_javascript(render @user) %>");

users_controller.rb

Before def create @user = User.new(user_params)

  respond_to do |format|
    if @user.save
      format.html { redirect_to @user, notice: 'User was successfully created.' }
      format.json { render :show, status: :created, location: @user }
      format.js
    else
    .
    .

After def create @user = User.new(user_params)

  respond_to do |format|
    if @user.save
    @users = User.all
      format.html { redirect_to @user, notice: 'User was successfully created.' }
      format.json { render :show, status: :created, location: @user }
      format.js
    else
    .
    .

Then everything works fine. These are actually very make sense for both, each for nil error and appended rendering behavior. Thanks for answering comment Rajesh. Next time, please try post it in answer section.