简体   繁体   English

Angular $ http和Rails 4 params

[英]Angular $http and Rails 4 params

I'm using the rails-api gem to have just a Rails API and using Angular to power my frontend. 我正在使用rails-api gem只有一个Rails API并使用Angular来支持我的前端。 Whenever I use $http, it will only work if I pass in params instead of data . 每当我使用$ http时,它只会在我传入params而不是data才能工作。 Here's an example with trying to log in a user and create a new session: 以下是尝试登录用户并创建新会话的示例:

'use strict';

app.controller('LoginCtrl', function($scope, $location, $http, tokenHandler) {
  $scope.login = function() {
    $http({
      url: 'http://localhost:3000/api/admins/sign_in',
      method: 'POST',
      params: $scope.admin
    }).success(function(data) {
      if (data.success) {
        $scope.ngModel = data.data.data;
        tokenHandler.set(data.data.auth_token);
        $location.path('/admin/blog');
      } else {
        $scope.ngModel = data;
        $scope.user.errors = data.info;
      }
    }).error(function(msg) {
      $scope.admin.errors = 'Something is wrong. Please try again.';
    });
  };
});

If instead of params I used data: { admin: $scope.admin } , Rails complains to me that params[:admin] is nil. 如果我使用data: { admin: $scope.admin }而不是params data: { admin: $scope.admin } ,Rails向我抱怨params[:admin]是零。 It seems to not be coming through at all. 它似乎根本没有通过。

However, if I use params, I get this: 但是,如果我使用params,我会得到:

Started POST "/api/admins/sign_in?email=raderj89@gmail.com&password=[FILTERED]" for 127.0.0.1 at 2014-09-07 20:08:04 -0400
Processing by Admin::SessionsController#create as HTML
  Parameters: {"email"=>"raderj89@gmail.com", "password"=>"[FILTERED]"}

Which I can work with. 哪个我可以合作。 It's just weird that it seems to only work when the request is processed as HTML. 奇怪的是它似乎仅在请求作为HTML处理时才起作用。 When I use data , I get this: 当我使用data ,我得到了这个:

Started OPTIONS "/api/admins/sign_in" for 127.0.0.1 at 2014-09-07 20:36:24 -0400
Processing by Admin::SessionsController#create as */*

Is it suppose to say processing by */* ? 它是否假设用*/*表示处理? I'd think it should understand it's supposed to process by json specifically. 我认为它应该理解它应该由json专门处理。

My sessions controller looks like this: 我的会话控制器看起来像这样:

class Admin::SessionsController < Devise::SessionsController
  skip_before_filter :verify_authenticity_token

  before_filter :authenticate_user!, except: [:create]
  respond_to :json

  # ...
end

The weird thing is I definitely got it working the first time just using data: { admin: $scope.admin } , but ever since, the params seem to never come through unless I use params: $scope.admin . 奇怪的是我第一次使用data: { admin: $scope.admin }时确实让它工作data: { admin: $scope.admin } ,但从那以后,除非我使用params: $scope.admin否则params似乎永远不会出现。

ALSO: 也:

I'm using Devise for authentication, and I had to add this to my ApplicationController: 我正在使用Devise进行身份验证,我不得不将其添加到我的ApplicationController:

class ApplicationController < ActionController::API
  include ActionController::MimeResponds

  before_filter :set_cors_headers
  before_filter :cors_preflight

  private 

    def set_cors_headers
      headers['Access-Control-Allow-Origin'] = AppConfig.client['origin']
      headers['Access-Control-Allow-Methods'] = 'GET,POST,PUT,DELETE,OPTIONS'
      headers['Access-Control-Allow-Headers'] = '*'
      headers['Access-Control-Max-Age'] = "3628800"
    end

    def cors_preflight
      head(:ok) if request.method == :options
    end
end

Anyone ever dealt with this before? 以前有人曾经处理过这个吗?

I've finally got it working and while I'm still confused, I think I've got somewhere close to what the problem was: My CORS configuration in my Rails API. 我终于让它工作了,虽然我仍然感到困惑,但我认为我已经接近问题所在:我的Rails API中的我的CORS配置。

From what I've learned, Angular sends data in JSON format by default. 据我所知,Angular默认以JSON格式发送数据。 This goes through as "Content-Type:application/json;charset=UTF-8", whereas in jQuery AJAX requests, it goes through as "Content-Type:application/x-www-form-urlencoded; charset=UTF-8", and is converted to a query string using $.param() . 这通过“Content-Type:application / json; charset = UTF-8”,而在jQuery AJAX请求中,它通过“Content-Type:application / x-www-form-urlencoded; charset = UTF-8” “,并使用$.param()转换为查询字符串。 I'll admit, I've probably heard this before, but haven't truly registered this fact and its effects until now. 我承认,我以前可能听过这个,但直到现在还没有真正记录这个事实及其影响。

In my application controller, I configured my CORS settings like so: 在我的应用程序控制器中,我配置了我的CORS设置:

def set_cors_headers
  headers['Access-Control-Allow-Origin'] = AppConfig.client['origin']
  headers['Access-Control-Allow-Methods'] = 'GET,POST,PUT,DELETE,OPTIONS'
  headers['Access-Control-Allow-Headers'] = '*'
  headers['Access-Control-Max-Age'] = "3628800"
end

def cors_preflight
  head(:ok) if request.method == :options
end

AppConfig is just an OpenStruct that tells my Rails API what origin to accept requests from. AppConfig只是一个OpenStruct,告诉我的Rails API接受请求的来源。 And then everything else was supposed to simply set the CORS headers. 然后其他一切都应该简单地设置CORS标头。

For some reason of which I'm still not sure, this wasn't working for JSON requests. 由于某些原因,我仍然不确定,这不适用于JSON请求。 I got the above code from a tutorial using Angular and Rails, and in the case of the tutorial, they manually stripped out the asset pipeline, leaving everything else about Rails in, whereas rails-api strips out some Rails configuration. 我从使用Angular和Rails的教程中获得了上述代码,在本教程的情况下,他们手动剥离了资产管道,留下了关于Rails的所有其他内容,而rails-api删除了一些Rails配置。 This may be why setting the CORS headers in ApplicationController wasn't working. 这可能是为什么在ApplicationController中设置CORS头不起作用的原因。

What did work was to use the rack-cors gem and then add this bit to development.rb: 做了什么工作是使用rack-cors gem然后将这个位添加到development.rb:

  config.middleware.use Rack::Cors do
    allow do
      origins 'localhost:9000'
      resource '*', :headers => :any, :methods => [:get, :post, :options, :delete]
    end
  end

This tells my app to accept requests from localhost:9000, and to accept any headers. 这告诉我的应用程序接受来自localhost:9000的请求,并接受任何标头。 I thought I was accomplishing that with headers['Access-Control-Allow-Headers'] = '*' in my ApplicationController, but I guess not. 我以为我在我的ApplicationController中用headers['Access-Control-Allow-Headers'] = '*'来完成它,但我猜不是。 Once I specified Rails to use those middleware settings, everything worked perfectly. 一旦我指定Rails使用这些中间件设置,一切都很完美。 My Rails API can now accept application/json from my Angular app. My Rails API现在可以从我的Angular应用程序接受application/json

If someone could fill in the gaps where I'm still confused, I'd appreciate it. 如果有人能填补我仍然困惑的空白,我会很感激。 But I hope this helps others. 但我希望这有助于其他人。

You can send either :params or :data (or both, I guess). 您可以发送:params或:data(或者两者,我猜)。 According to the angularjs docs at https://docs.angularjs.org/api/ng/service/$http 根据https://docs.angularjs.org/api/ng/service/$http上的angularjs文档

params – {Object.} – Map of strings or objects which will be turned to ?key1=value1&key2=value2 after the url. params - {Object。} - 在url之后将转向的字符串或对象的映射?key1 = value1&key2 = value2。 If the value is not a string, it will be JSONified. 如果该值不是字符串,则它将是JSONified。

data – {string|Object} – Data to be sent as the request message data. data - {string | Object} - 要作为请求消息数据发送的数据。

The controller is expecting http-type parameters/form data, so passing the object via params works - it gets converted, whilst passing the same via :data doesn't because it doesn't get converted. 控制器期望http类型参数/表单数据,因此通过params传递对象是有效的 - 它被转换,同时传递相同的通道:数据不会因为它没有被转换。

I don't know if there is a smart way to unpack the data format at the Rails Controller end, but you can convert the object within your $http request into serialized parameters using $.param(data) http://api.jquery.com/jQuery.param/ 我不知道是否有一种智能方法可以在Rails Controller端解压缩数据格式,但您可以使用$ .param (data) http://api.jquery将$ http请求中的对象转换为序列化参数.COM / jQuery.param /

data: $.param($scope.your_data_object) e.g. $scope.admin

and then unpack params[:data] at the controller. 然后在控制器上解压缩params [:data]。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM