0

I'm trying to do a form submission through AJAX in Rails and I am not too sure what is wrong here. I got everything to work using "remote: true" but I want to gain a better understanding of how the AJAX works with jQuery. This is my javascript code:

$(document).ready(function(){
  $("#new_user_friendship").on("submit", function(event){
    event.preventDefault();
    var friendId = $("#user_friendship_friend_id").val();
    var _this = $(this);

    $.ajax({
      url: "/user_friendships",
      data: _this.serialize(),
      method: "POST",
      dataType: "json",
      success: function(data){
        console.log(data);
        friendButton.hide();
        $(".friend-request-form").html("<p>Friend request sent</p>");
      }
    });
  });
});

I am suspecting this line url: "/user_friendships/new?friend_id="+friendId containing the url is the culprit of my errors. I wrote this because a hidden field is being passed as a person's friend id but it throws a "404 error", I've also tried url: "/user_friendships" which doesn't return any errors but it also doesn't properly execute the Javascript as I expected.

This is the corresponding form_for that the AJAX request is sent to:

  <div class="friend-request-form">
      <%= form_for current_user.user_friendships.build(friend_id: @user), id: "new_user_friendship", method: :post do |f| %>

        <%= f.hidden_field :friend_id, value: @user.id  %>      
        <%= submit_tag "Send friend request", class: "button radius tiny", id: "friend-request-button" %>

      <% end %>
  </div>

What this form does is it sends a friend request to another user using a hidden field.

And in my user_friendships_controller.rb I have this code:

def create
    if params[:user_friendship] && params[:user_friendship].has_key?(:friend_id)
        @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 that friend request." 
                        redirect_to user_path(@friend)
                    end
                    format.json {render json: @user_friendship.to_json, status: :precondition_failed}

                else        
                    format.html do
                        flash[:success] = "Friend request sent"
                        redirect_to user_path(@friend)
                    end
                    format.json {render json: @user_friendship.to_json, status: :precondition_failed}
                end
            end 


    else
        flash[:error] = "Friend required"
        redirect_to root_path
    end
end

If anyone can provide any suggestions or feedback that'd be great!

UPDATE:

Now that I added in data: _this.serialize() and changed the url to: url: "/user_friendships" I'm now getting a 412 (Precondition Failed) error. Despite this error the data is actually being saved into the database. Does anyone know why I'm getting this 412 (Precondition Failed) error?

Jamaal
  • 1,441
  • 1
  • 13
  • 29
  • Where you passing the data?? – BKM Mar 21 '14 at 04:00
  • i'm passing it to the id="new_user_friendship" in the form_for – Jamaal Mar 21 '14 at 04:04
  • `url: "/user_friendships/new?friend_id="+friendId,` is the url path valid according to your file structure – sanjeev Mar 21 '14 at 04:04
  • @sanjeev Ya that's the url path/structure that was generated when I was submitting POST requests without using AJAX, just to confirm isn't that what your are supposed to pass into the "url" option in the ajax call? – Jamaal Mar 21 '14 at 04:07

2 Answers2

1

Add a data attribute to the post params instead of passing it in the url:

$.ajax({
  url: "/user_friendships",
  data: { user_friendship: { friend_id: friendId } }, // <<< Updated
  method: "POST",
  dataType: "json",
  success: function(data){
    console.log(data);
    friendButton.hide();
    $(".friend-request-form").html("<p>Friend request sent</p>");
  }
});

Update

The url should be /user_friendships, assuming that you're using RESTful actions. Have a look to this article about REST in Rails.

Also, when you do an AJAX request like this, your are not sending the rails authenticity tokens that are crated by the form helper. This may be the cause of your 412 (Precondition Failed) error.

See: Understanding the Rails Authenticity Token

Community
  • 1
  • 1
Sergio A.
  • 3,566
  • 2
  • 18
  • 29
  • data: {friend_id: friendId} doesn't work I think I need to add something else, would I need to serialize the data as well? – Jamaal Mar 21 '14 at 04:09
  • I had not seen the user_friendship param in your controller. I have updated the answer. – Sergio A. Mar 21 '14 at 04:30
  • Now I'm getting a 412 precondition failed error from your changes but with a url of: url: "/user_friendships/", do you know why this might be happening? – Jamaal Mar 21 '14 at 04:35
  • Ok, that might be because of the authenticity token, I've updated the answer again. – Sergio A. Mar 21 '14 at 04:46
  • Ya changing the dataType to "jsonp" prevents the 412 error from showing, but this line: console.log(data); and these 2 don't do anything afterwards friendButton.hide(); $(".friend-request-form").html("

    Friend request sent

    "); Do you have any ideas why this might be?
    – Jamaal Mar 21 '14 at 04:47
1

There is something I do not understand, with the dataType json, you said that you had a precondition failed status right ? But you wrote

format.json {render json: @user_friendship.to_json, status: :precondition_failed}

So I don't think there is any problem, indeed, it seems to work fine, as you explicitly passed the status in your render command, try removing it and I think you will have a 200 (success) status instead. Of course, you can keep the previous post ajax request, or use this short version

$.post(
/user_friendships', 
{ user_friendship: { friend_id: friendId } }, 
function(){
    console.log(data);
    friendButton.hide();
    $(".friend-request-form").html("<p>Friend request sent</p>");
},
'json')
Uelb
  • 3,367
  • 2
  • 17
  • 29
  • 1
    Thank you I totally forgot about that in my controller, such a stupid mistake, thank you!!!!! – Jamaal Mar 21 '14 at 05:10