Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby Building Social Features in Ruby on Rails Using AJAX Implementing AJAX: Part 3

Brandon Hay
Brandon Hay
1,109 Points

Missing step in implementing AJAX

For everyone using Rails 4 for this tutorial you need to include the :remote => true attribute into your button. AJAX wouldn't work for me without this:

<%= link_to "Add Friend", new_user_friendship_path(friend_id: @user), id: 'add-friendship', data: { friend_id: @user.to_param }, class: 'btn btn-primary', :remote => true %>

I am stuck right now here and I use Rails 4. I added :remote => true, but it does not work with or without remote. Does anyone has the same issue? If I don't add :remote => true, it adds friends using html, but not json. If I add :remote => true, I see it tries to add it but looks at new method, not at create method. So, I'm stuck :(

Brandon Barrette
Brandon Barrette
20,485 Points

What's the code in your view and your controller?

10 Answers

Brandon Barrette
Brandon Barrette
20,485 Points

The error is in the AJAX route. What I want you to do is go to your terminal and type:

rake routes

Then search in that list for the CREATE UserFriendship route. Check that against the route you see in the URL of the AJAX call.

You can also probably see this error if you open Google Chrome and go to View > Developer > Javascript Console. Click on the Console, you should see a red error after you click on the button.

Hi Brandon, thank you for helping out. I changed the route instead of user_friendship_path to user_friendships_path, I added "s" to friendships. But It stays the same, it still processes it as HTML when I press button "Add Friend".

Brandon Barrette
Brandon Barrette
20,485 Points

So there seems to also be an error in your create method:

@friend = User.find(params[:user_friendship][:friend_id])

This line doesn't make sense, I think you mean:

@friend = User.find_by(profile_name: params[:user_friendship][:friend_id])
Brandon Hay
Brandon Hay
1,109 Points

I think I can help on this one. Check out your gemfile. Do you have the turbolinks gem installed? If so, remove that from your gemfile and from any other files that reference it. I had this same exact problem and removing the turbolinks gem solved it for me.

Brandon Barrette
Brandon Barrette
20,485 Points

I wouldn't remove turbolinks, instead do some research of how to make this work with turbolinks.

For example, instead of:

$(document).on("ready", function() {

\\this only fires when the page is initially loaded

});

try

$(document).on("page:change", function() {

\\this fires when the page is loaded every time by turbolinks

});

Brandon, here are my user_friendships_controller.rb

       class UserFriendshipsController < ApplicationController

before_filter :authenticate_user!
respond_to :html, :json

def index
 @user_friendship = current_user.user_friendships.all
end

def accept
 @user_friendship = current_user.user_friendships.find(params[:id])
 if @user_friendship.accept!
   flash[:notice] = "You are now friends"
  else
   flash[:error] = "That friendship can't be accepted."
  end
 redirect_to user_friendships_path
end

def new
 if params[:friend_id]
 @friend = User.where(profile_name: params[:friend_id]).first
 raise ActiveRecord::RecordNotFound if @friend.nil?
 @user_friendship = current_user.user_friendships.new(friend: @friend)

 else
  flash[:alert] = 'Friend Require'
   end
     rescue ActiveRecord::RecordNotFound
     render file: 'public/404', status: :not_found
end

def create
if params[:user_friendship] && params[:user_friendship].has_key?(:friend_id)
 #@friend = User.where(profile_name: params[:user_friendship][:friend_id]).first
 @friend = User.find(params[:user_friendship][:friend_id])
 @user_friendship = UserFriendship.request(current_user, @friend)
 respond_to do |format|
  if @user_friendship.new_record?
   format.html do
    flash[:error] ='There was a problem creating this friendship'
    redirect_to profile_path(@friend)
   end 
   format.json {render json: @user_friendship.to_json, status: :precondition_failed }
  else 
   format.html do
    flash[:notice] ='Friend request sent.'
    redirect_to profile_path(@friend)
   end
   format.json {render json: @user_friendship.to_json }
  end
 end 
else
   flash[:error] = "Friend Required"
   redirect_to root_path
 end 

 def user_friendship_params
    params.require(:user).permit(:user_id, :friend_id, :friend, :first_name, :profile_name, :user_friendship, :state)

end 

end

def edit
 @user_friendship = current_user.user_friendships.find(params[:id]).decorate
 @friend = @user_friendship.friend
end

def destroy
 @user_friendship = current_user.user_friendships.find(params[:id])
 if @user_friendship.destroy
  flash[:notice] ='Friendship destroyed.'
 end 
 redirect_to user_friendships_path
end


end

            ```

Here is show.html.erb

<div class="page-header">

<h1> <%= @user.profile_name  %>   </h1>
</div>

<% if signed_in? %>
 <div id="friend-status">
  <% if current_user.friends.include?(@user) %>
   <%= link_to "Edit Friendship", edit_user_friendship_path(friend_id: @user), class: 'btn btn-success' %>
  <% else %>
   <%= link_to "Add Friend", new_user_friendship_path(friend_id: @user), class: 'btn btn-success', id: 'add-friendship', data: { friend_id: @user.to_param}%>
  <% end %>
 </div>
<% end %>

<% if @comments %>
  <% @comments.each do |comment| %>
    <div class="well">
     <%= comment.body %>
     <hr />
     <%= link_to time_ago_in_words(comment.created_at), comment_path(comment) %> ago
     </div>
     <% end %>

 <% end %>

And here user_friendships.js

$(document).ready(function() {

  $('#add-friendship').click(function(event) {
      event.preventDefault();
      var addFriendshipbtn = $(this);
      $.ajax({
         url: Routes.user_friendship_path({user_friendship: { friend_id: addFriendshipbtn.data('friendId') }}),
         dataType: 'json',
         type: 'POST',
         success: function(e) {
          addFriendshipbtn.hide();
          $('#friend-status').html("<a href='#' class='btn btn-success'> Friendship Requested</a>");
         }
      });    
  });

});

When I look at terminal it gives me: Started POST "/user_friendships" for 127.0.0.1 at 2014-11-02 08:30:20 -0800 Processing by UserFriendshipsController#create as HTML

So it's processes it as HTML and not as JS.

Brandon, I followed the video tutorial and they had this line. I changed it for the line you suggested and I added :remote => true again because without it it would create it as html. I read in Rails documentation that remote command will trigger AJAX. So Now when I press button Add Friend nothing happens, however when I reload current page and press it again, it works. I tried like 5 times and when page loads nothing happens and "Add Friend" only works after reloading the page.

Brandon Barrette
Brandon Barrette
20,485 Points

The video tutorial was written for rails 3 and you are using rails 4. If you use the find method, it returns ALL instances, so you would have to call .first on that call. If you use find_by, it will automatically just take the first one called (this is new to rails 4)

You are having javascript issues is my guess.

I deleted turbolinks, it works. Then after Brandon message advising not to delete turbo links, I added them back and changed js file and it works too. Thank you for your help! It works now.

Ben Wong
Ben Wong
2,652 Points

Tried deleting turbolinks, and adding this $(document).on("page:change", function() {

but no go:(

any other suggestions?

Ben Wong
Ben Wong
2,652 Points

Tried deleting turbolinks, and adding this $(document).on("page:change", function() {

but no go:(

any other suggestions?

Ben Wong
Ben Wong
2,652 Points

Got it working. Have to remove user_friendship.coffee file and added :remote => true.