javascript - Rails Ajax JS vs JSON confusion - Stack Overflow

Using Rails 4, I want to use Ajax form post using :remote => true and I want to be able to get back

Using Rails 4, I want to use Ajax form post using :remote => true and I want to be able to get back the response in json format so I can make use of any error messages in case of failure.

The form post is hitting my controller action fine. Controller action:

def create
    @ment_hash = ment_params
    @obj = @ment_hash[:mentable_type].constantize.find(@ment_hash[:mentable_id])
    @ment = Comment.build_from(@obj, current_user.id, @ment_hash[:body])
    respond_to do |format|
        if @ment.save
            if @ment_hash[:reply_to].to_i > 0
                @parentment = Comment.find(@ment_hash[:reply_to].to_i)
                @ment.move_to_child_of(@parentment)
            end

            format.js { render :template => "ments/create.js.erb", :status => :created }
        else
            format.js { render :template => "ments/create.js.erb", :status => :unprocessable_entity }
        end
    end
end

The controller action will render the create.js.erb regardless of success or error as expected. But if I include format.json it will never respond using json. I think this is because Ajax remote: true requests will always respond using js.

  1. How do I get the ajax request to respond with json?

  2. With this observation that rails ajax requests respond with js format, I am further confused by the example provided here: .html where the successful save response provides the js format but the error response does not provide any js format.

I would think this would error for an ajaxError response because the js format is not available?:

def create
  @user = User.new(params[:user])

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

Using Rails 4, I want to use Ajax form post using :remote => true and I want to be able to get back the response in json format so I can make use of any error messages in case of failure.

The form post is hitting my controller action fine. Controller action:

def create
    @ment_hash = ment_params
    @obj = @ment_hash[:mentable_type].constantize.find(@ment_hash[:mentable_id])
    @ment = Comment.build_from(@obj, current_user.id, @ment_hash[:body])
    respond_to do |format|
        if @ment.save
            if @ment_hash[:reply_to].to_i > 0
                @parentment = Comment.find(@ment_hash[:reply_to].to_i)
                @ment.move_to_child_of(@parentment)
            end

            format.js { render :template => "ments/create.js.erb", :status => :created }
        else
            format.js { render :template => "ments/create.js.erb", :status => :unprocessable_entity }
        end
    end
end

The controller action will render the create.js.erb regardless of success or error as expected. But if I include format.json it will never respond using json. I think this is because Ajax remote: true requests will always respond using js.

  1. How do I get the ajax request to respond with json?

  2. With this observation that rails ajax requests respond with js format, I am further confused by the example provided here: http://edgeguides.rubyonrails/working_with_javascript_in_rails.html where the successful save response provides the js format but the error response does not provide any js format.

I would think this would error for an ajaxError response because the js format is not available?:

def create
  @user = User.new(params[:user])

  respond_to do |format|
    if @user.save
      format.html { redirect_to @user, notice: 'User was successfully created.' }
      format.js   {}
      format.json { render json: @user, status: :created, location: @user }
    else
      format.html { render action: "new" }
      format.json { render json: @user.errors, status: :unprocessable_entity }
    end
  end
end
Share Improve this question asked Jul 30, 2015 at 23:40 joshweirjoshweir 5,6473 gold badges42 silver badges65 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 8

The controller action will render the create.js.erb regardless of success or error as expected. But if I include format.json it will never respond using json. I think this is because Ajax remote: true requests will always respond using js

First off, your assumption is incorrect. Rails remote: true hooks into what's known as the UJS driver, which makes a lot of the work involved in making an XHR request simpler. However, you could achieve the same behaviour by having a form_for or form_tag and handling the form submission purely in JS via jQuery's excellent $.ajax().

I'd suggest you first delete the create.js.erb - this will always be processed to return a script response, and you want to render JSON instead.

You can also be a bit more explicit here,

format.json { render json: { @user, status: :created, location: @user } }

Under the covers, Rails is calling #to_json on your Ruby objects such as AR models, to simple Hashes.

Once you've removed the create.js.erb, go the view where you are rendering your form. Look for the form element in the DOM, you can casually look for it via the inspector console via $('form'). It's better to identify it via a class or directly, its id. Let's assume your form's selector is $('#ments-form').

You'll want to add another JS file to your app/assets/javascripts/application.js Sprockets manifest, and inside that file

$(function(){
    var $mentForm = $('#ments-form');

    $mentForm.on('ajax:error', function(e, xhr, status, error) {
        console.log('Error: %O', $(this).append(xhr.responseText));
    });

    $mentForm.on('ajax:success', function(e, data, status, xhr) {
        console.log('Data: %O', data);
    });

});

The JS snippet above is a start, and will fire when those jquery-ujs events are triggered, placing debugging output into the console. On an XHR error, you'll get error info, on success the JSON data will be shown instead.

Addendum:

The format.js in the respond_to block is purely for processing the create.js.erb, which in the example provided does this $("<%= escape_javascript(render @user) %>").appendTo("#users"); - it uses the user instance to figure out the DOM selector, and appends that to a DIV with id 'users' into the DOM.

Personally, I find it's simpler to stick to JSON for consistencies sake and achieve the same behaviour via the success handler, although YMMV.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745091404a4610714.html

相关推荐

  • javascript - Rails Ajax JS vs JSON confusion - Stack Overflow

    Using Rails 4, I want to use Ajax form post using :remote => true and I want to be able to get back

    14小时前
    30

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信