winston
winston

Reputation: 3100

Ajax button no longer updates in Rails app

I implemented a "follow" feature from Michael Hartl's Rails tutorial. It worked fine for months but now all of a sudden the button no longer updates once it quits. I don't get any Javascript errors, nor do I get any errors in the Rails console. Clicking on the button will successfully create/destroy the "relationship". I only get an error in the Rails console when I try to click on the button again because it's trying to redo the transaction.

I do precompile my assets but this was never a problem. I had always precompiled my assets and pushed the app to Heroku and the button worked fine. The only change I implemented recently was the addition of the simple_form and haml-rails gems in order to get the mailboxer gem working right. I'm not sure if they are related but I figured that may help debug.

How did this break and how can I fix it? THANKS!

Relevant code:

Controller:

class RelationshipsController < ApplicationController

  def create
    @user = User.find(params[:relationship][:followed_id])
    current_user.follow!(@user)
   respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end

  def destroy
    @user = Relationship.find(params[:id]).followed
    current_user.unfollow!(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end
end

follow form

<% unless current_user == @user %>
  <% if current_user.following?(@user) %>
    <%= render 'unfollow' %>
  <% else %>
    <%= render 'follow' %>
  <% end %>

follow

<%= form_for(current_user.relationships.build(followed_id: @user.id),
             remote: true) do |f| %>
  <div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-primary btn-small" %>
<% end %>

unfollow

<%= form_for(current_user.relationships.find_by_followed_id(@user),
             html: { method: :delete },
             remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-primary btn-small" %>
<% end %>

create.js.erb

$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= @user.followers.count %>')

destroy.js.erb

$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>")
$("#followers").html('<%= @user.followers.count %>')

application.js

// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.

//= require bootstrap
//= require jquery
//= require jquery-ui
//= require jquery.tokeninput
//= require_tree .

I used to have //= require jquery_ujs in the application.js but I had to remove it because clicking on the Follow button would cause the click to occur twice. Removing that line solved that problem, but the Ajax just doesn't seem to be updating the button anymore and I can't figure out why.

EDIT:

Rails console does show that the request is being received. I can even refresh the page and then the button will update:

Started DELETE "/relationships/32" for 127.0.0.1 at 2014-01-13 21:35:37 -0500
Processing by RelationshipsController#destroy as JS
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"---edited---", "commit"=>"Unfollow", "id"=>"32"}
  Relationship Load (0.4ms)  SELECT "relationships".* FROM "relationships" WHERE "relationships"."id" = $1 LIMIT 1  [["id", "32"]]
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 2 LIMIT 1
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
  Relationship Load (0.4ms)  SELECT "relationships".* FROM "relationships" WHERE "relationships"."follower_id" = 1 AND "relationships"."followed_id" = 2 LIMIT 1
   (0.1ms)  BEGIN
  SQL (0.3ms)  DELETE FROM "relationships" WHERE "relationships"."id" = $1  [["id", 32]]
   (1.5ms)  COMMIT
  Rendered users/_follow.html.erb (2.5ms)
   (0.7ms)  SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = 2
  Rendered relationships/destroy.js.erb (6.0ms)
Completed 200 OK in 17.4ms (Views: 8.0ms | ActiveRecord: 4.2ms)

The Javascript console doesn't show any errors at all in Chrome.

EDIT 2 My network tab:

Network tab in Chrome Javascript console

Upvotes: 0

Views: 574

Answers (3)

winston
winston

Reputation: 3100

Found the issue. I was missing the <div id="follow_form"> on the follow form:

<% unless current_user == @user %>
 <div id="follow_form">
  <% if current_user.following?(@user) %>
    <%= render 'unfollow' %>
  <% else %>
    <%= render 'follow' %>
  <% end %>
</div>

Thanks everyone for your help!

Upvotes: 0

Richard Peck
Richard Peck

Reputation: 76774

If your create.js.erb works (from your alert), the problem is going to be with the rendering of your JS

This is your current create.js.erb:

$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= @user.followers.count %>')
  1. Does #follow_form still exist?
  2. Can you call users/unfollow?
  3. Does #followers exist?

I think it's going to be a problem in your create.js.erb. You can check this by clicking on right-click -> inspect element -> network -> request you just sent -- if there's an error, it will be red

Upvotes: 2

edudepetris
edudepetris

Reputation: 714

in Js console look up the Network tag and check the preview of ajax request to verify what respond the server, maybe the ids or class names are different

Upvotes: 0

Related Questions