Rails API with devise, can't 运行 POST #create method with JSON call from client

Rails API with devise, can't run POST #create method with JSON call from client

所以我正在尝试用设计创建一个 Rails API。我的客户端可以很好地使用 GET,但我不能执行 POST 类型的调用。如果我尝试创建一个用户,我会不断收到以下设计 html 表单作为响应。

<h2>Sign up</h2>

<form class="new_user" id="new_user" action="/users" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="RGZxLuXcOCbxKVdpFc/wSAKEp3wcxqpfnvmv0nstEcOppPyViWcmdu+dPt84XQeSkCmwRg0REZN+vTdX1j+MOQ==" />
      <div id="error_explanation">
      <h2>2 errors prohibited this user from being saved:</h2>
      <ul><li>Email can&#39;t be blank</li><li>Password can&#39;t be blank</li></ul>
    </div>


  <div class="field">
    <div class="field_with_errors"><label for="user_email">Email</label></div><br />
    <div class="field_with_errors"><input autofocus="autofocus" type="email" name="user[email]" id="user_email" /></div>
  </div>

  <div class="field">
    <div class="field_with_errors"><label for="user_password">Password</label></div>
    <em>(4 characters minimum)</em>
    <br />
    <div class="field_with_errors"><input autocomplete="off" type="password" name="user[password]" id="user_password" /></div>
  </div>

  <div class="field">
    <label for="user_password_confirmation">Password confirmation</label><br />
    <input autocomplete="off" type="password" name="user[password_confirmation]" id="user_password_confirmation" />
  </div>

  <div class="actions">
    <input type="submit" name="commit" value="Sign up" />
  </div>
</form>
  <a href="/users/sign_in">Log in</a><br />



  <a href="/users/confirmation/new">Didn&#39;t receive confirmation instructions?</a><br />

有趣的是,一开始我会得到一个 "Can't verify CSRF token authenticity" 错误,所以我在我的 [=62= 中添加了 beforeSend ] 称呼。这将改变我对 OPTIONS 的调用,即使它被指定为 POST。

我的电话:

$(document).on('page:change', function(){
  $('body').on('submit', 'form.create_new_user', function(e){
    e.preventDefault();
    var user_data = $(this).serializeJSON();
    $.ajax({
      url: Host.address + '/users',
      beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
      type: 'post',
      datatype:'json',
      data: {info: {full_name: user_data.full_name,
                    email: user_data.email,
                    password: user_data.password,
                    password_confirmation: user_data.password_confirmation}}
    }).done(function(response){
      console.log(response)
      if (response.success.success) {
        logInGoToWithNotice(response, '/', 'Thank you for signig up');
      } else{
        alert("User wasn't created. Please try again.")
      };
    });
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

并且 API 这样做:

Started OPTIONS "/users" for ::1 at 2015-09-30 14:09:49 +0200

ActionController::RoutingError (uninitialized constant RegistrationsController):
...

如果我现在删除 beforeSend,我会再次得到表格,只是 "Can't verify CSRF token authenticity" 错误不会在那里,但我会成功 POST,仍然 returns html 形式。

Started POST "/users" for ::1 at 2015-09-30 14:25:57 +0200  

Processing by Devise::RegistrationsController#create as */*
Parameters: {"info"=>{"full_name"=>"User Admin", "email"=>"user.admin@email.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}
  (0.1ms)  BEGIN
  (0.1ms)  ROLLBACK
Rendered /Users/antonpot/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/devise-3.5.2/app/views/devise/shared/_links.html.erb (0.2ms)
Rendered /Users/antonpot/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/devise-3.5.2/app/views/devise/registrations/new.html.erb (3.5ms)  
Completed 200 OK in 9ms (Views: 4.7ms | ActiveRecord: 0.2ms)

现在,如果我查看我的用户控制器,我可以看到我什至从未 运行 我的 #create,因为它从不打印 p "C"*99

class Users::RegistrationsController < Devise::RegistrationsController
  def create
    p "C"*99
    user = User.new
    user.full_name = user_params[:full_name]
    user.email = user_params[:email].downcase
    user.password = user_params[:password]
    user.password_confirmation = user_params[:password_confirmation]
    if user.save
      render json: {success:{success: true, user_id: user.id, errorMessage: nil, errorNumber: 201}}
    else
      render json: {success:{success: false, errorMessage: user.errors.messages.to_s, errorNumber: 400}}
    end
  end
end

为什么我不能调用它?我需要做什么才能让它起作用?

第一

这个问题是因为跨站点脚本问题。 client url 不同于 api urlHTTP method OPTIONS 是浏览器发出的 飞行前 请求,用于确定是否应允许跨域 AJAX 请求。

如果允许跨域 AJAX 请求,将发送实际请求 POST

所以你需要在你的服务器上允许跨域AJAX请求。

第二

确保您的 routes.rb 设置正确。

您需要配置您的设备并指示他使用您的 customized registration_controller 而不是 default devise registration controller

routes.rb 中的 devise_for :users 调整为如下所示:

devise_for :users, controllers: { registrations: "users/registrations"}

假设 customized registration class 存在于 users 文件夹中