PATCH to Rails app from iOS Client Returning Status 422

痞子三分冷 提交于 2019-12-13 21:25:11

问题


I have a Rails app with a Business model object with a count of visits. I have an iOS client that interacts with this Rails app using AFNetworking 2.0, and when a user taps a business in the app, it sends a PATCH to the Rails app, incrementing visits for that business. However, I'm getting a status code 422 "Unprocessable Entity" error back from the server, and the business's visits count on the server is not getting incremented.

AFHTTPSessionManager - iOS

- (NSURLSessionDataTask *)visitVenue:(NOTVenue *)venue withCompletionBlock:(void (^)(BOOL success))completionBlock {
NSURLSessionDataTask *dataTask = [self PATCH:[NSString stringWithFormat:@"businesses/%li.json", (long)[venue.identifier integerValue]]
                                  parameters:@{@"visits": @(venue.numberOfVisits + 1)}
                                     success:^(NSURLSessionDataTask *task, id responseObject) {
                                         NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;

                                         if (httpResponse.statusCode == 200) {
                                             dispatch_async(dispatch_get_main_queue(), ^{
                                                 completionBlock(YES);
                                             });
                                         } else {
                                             dispatch_async(dispatch_get_main_queue(), ^{
                                                 completionBlock(NO);
                                             });
                                         }
                                     }
                                     failure:^(NSURLSessionDataTask *task, NSError *error) {
                                         dispatch_async(dispatch_get_main_queue(), ^{
                                             completionBlock(NO);
                                         });
                                     }];

return dataTask;

}

Businesses Controller - Rails

# PATCH/PUT /businesses/1
# PATCH/PUT /businesses/1.json
def update
  respond_to do |format|
    if @business.update(business_params)
      format.html { redirect_to @business, notice: 'Business was successfully updated.' }
      format.json { head :no_content }
    else
      format.html { render action: 'edit' }
      format.json { render json: @business.errors, status: :unprocessable_entity }
    end
  end
end

回答1:


If the web API allows to increment a model objects's counter, it should have a dedicated "method" for that.

Generally, an Increment Counter feature won't work reliable if the client itself increments the counter performed on a local copy which it received before from the server and then tries to update the server's value via composing a PATCH request where the client sends just the value local_counter+1. In the meantime, other clients could have the same idea, in which case the counter value on the server would be become corrupt. Also, one could update the counter on the server to any value - which is certainly not desired.

This has the consequence, that the counter variable MUST be read only for the clients.

There must be other means (defined by the web API) where a client can accomplish this. For example, a REST API would define a particular "resource" (e.g. some sort of "ticket" or "reservation") which a client can create. The creation of this resource will have the effect of incrementing the counter variable on the server.

Edit

If you are testing a web API, the command line tool curl is invaluable:

Test the PATCH request:

In Terminal.app enter this command:

curl -sSv -X PATCH \
    -H "Content-Type: application/json" \
    -H "Accept: application/json" \
    -d '{"email”:”jappleseed@mail.com"}' \
    http://localhost:3000/api/v1/users/123 \
    | python -m json.tool



回答2:


The correct solution for this was found on the Rails API site. Here is the code:

class ApplicationController < ActionController::Base
  protect_from_forgery
  skip_before_action :verify_authenticity_token, if: :json_request?

  protected

  def json_request?
    request.format.json?
  end
end


来源:https://stackoverflow.com/questions/21303258/patch-to-rails-app-from-ios-client-returning-status-422

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!