Getting ActionController::RoutingError (No route matches [OPTIONS] "/users" when trying to POST data to RAils server with AngularJS

10,628

Rails cannot process [OPTIONS] requests

You have to install rack-cors to process CORS.

Here's where your problem comes from:

  resources :users do
    collection { post :create_user , via: :options  }
    # via: :options ?

  end
Share:
10,628
Trusislv1
Author by

Trusislv1

Updated on June 08, 2022

Comments

  • Trusislv1
    Trusislv1 over 1 year

    Having issue when trying to POST data to Rails server from my AngularJS side.

    The server error:

    ActionController::RoutingError (No route matches [OPTIONS] "/users"):
      actionpack (4.1.9) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
      actionpack (4.1.9) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
      railties (4.1.9) lib/rails/rack/logger.rb:38:in `call_app'
      railties (4.1.9) lib/rails/rack/logger.rb:20:in `block in call'
      activesupport (4.1.9) lib/active_support/tagged_logging.rb:68:in `block in tagged'
      activesupport (4.1.9) lib/active_support/tagged_logging.rb:26:in `tagged'
      activesupport (4.1.9) lib/active_support/tagged_logging.rb:68:in `tagged'
      railties (4.1.9) lib/rails/rack/logger.rb:20:in `call'
      actionpack (4.1.9) lib/action_dispatch/middleware/request_id.rb:21:in `call'
      rack (1.5.5) lib/rack/methodoverride.rb:21:in `call'
      rack (1.5.5) lib/rack/runtime.rb:17:in `call'
      activesupport (4.1.9) lib/active_support/cache/strategy/local_cache_middleware.rb:26:in `call'
      rack (1.5.5) lib/rack/lock.rb:17:in `call'
      actionpack (4.1.9) lib/action_dispatch/middleware/static.rb:84:in `call'
      rack (1.5.5) lib/rack/sendfile.rb:112:in `call'
      railties (4.1.9) lib/rails/engine.rb:514:in `call'
      railties (4.1.9) lib/rails/application.rb:144:in `call'
      rack (1.5.5) lib/rack/content_length.rb:14:in `call'
      thin (1.6.3) lib/thin/connection.rb:86:in `block in pre_process'
      thin (1.6.3) lib/thin/connection.rb:84:in `catch'
      thin (1.6.3) lib/thin/connection.rb:84:in `pre_process'
      thin (1.6.3) lib/thin/connection.rb:53:in `process'
      thin (1.6.3) lib/thin/connection.rb:39:in `receive_data'
      eventmachine (1.0.8) lib/eventmachine.rb:193:in `run_machine'
      eventmachine (1.0.8) lib/eventmachine.rb:193:in `run'
      thin (1.6.3) lib/thin/backends/base.rb:73:in `start'
      thin (1.6.3) lib/thin/server.rb:162:in `start'
      rack (1.5.5) lib/rack/handler/thin.rb:16:in `run'
      rack (1.5.5) lib/rack/server.rb:264:in `start'
      railties (4.1.9) lib/rails/commands/server.rb:69:in `start'
      railties (4.1.9) lib/rails/commands/commands_tasks.rb:81:in `block in server'
      railties (4.1.9) lib/rails/commands/commands_tasks.rb:76:in `tap'
      railties (4.1.9) lib/rails/commands/commands_tasks.rb:76:in `server'
      railties (4.1.9) lib/rails/commands/commands_tasks.rb:40:in `run_command!'
      railties (4.1.9) lib/rails/commands.rb:17:in `<top (required)>'
      bin/rails:8:in `require'
      bin/rails:8:in `<top (required)>'
      spring (1.3.6) lib/spring/client/rails.rb:28:in `load'
      spring (1.3.6) lib/spring/client/rails.rb:28:in `call'
      spring (1.3.6) lib/spring/client/command.rb:7:in `call'
      spring (1.3.6) lib/spring/client.rb:26:in `run'
      spring (1.3.6) bin/spring:48:in `<top (required)>'
      spring (1.3.6) lib/spring/binstub.rb:11:in `load'
      spring (1.3.6) lib/spring/binstub.rb:11:in `<top (required)>'
      bin/spring:13:in `require'
      bin/spring:13:in `<top (required)>'
      bin/rails:3:in `load'
      bin/rails:3:in `<main>'
    

    So here will be my Rails server controllers and routes files.

    User Controller

    class UsersController < ApplicationController
    
      def index
        respond_to do |format|
          format.json {render json: { name: 'Jonhy'}, callback: params[:callback]}
        end
      end
    
      def new
    
      end
    
      def create_user
        puts user_params
        @user = User.new(user_params)
        if @user.save
          render json: { error: false }, layout: false
        else
          render json: { error: true }, layout: false
        end
      end
    
      def show
    
      end
    
      def user_params
        params.require(:user).permit(:email, :password, :password_confirmation)
      end
    end
    

    Application Controller

    class ApplicationController < ActionController::Base
      # Prevent CSRF attacks by raising an exception.
      # For APIs, you may want to use :null_session instead.
      protect_from_forgery with: :exception
    
      before_filter :allow_ajax_request_from_other_domains
    
     def allow_ajax_request_from_other_domains
       headers['Access-Control-Allow-Origin'] = 'http://localhost:8001'
       headers['Access-Control-Request-Method'] = '*'
       headers['Access-Control-Allow-Headers'] = '*'
     end
    end
    

    Routs

    Rails.application.routes.draw do
    
      root 'home#index'
      resources :users do
        collection { post :create_user , via: :options  }
      end
    end
    

    And here is my AngularJS where i make the POST Ajax.

    var App = angular.module('OutOfBox', ['ng.deviceDetector','ngRoute','ngResource']);
    App.factory('Users',
    
      function($resource){
        var users =
         $resource('http://127.0.0.1\\:8001/:user', {user:'users'}, {
            query: {method:'GET', isArray: true},
            save: {method:'POST', isArray: false}
         });
         return users;
      }
    );
    App.controller('MainCtrl', ['$scope','$http','Users', function($scope,$http,Users) {
        $scope.user = [];
        $scope.responsive = [];
        $scope.submit = function() {
          if ($scope.users.email && $scope.users.password && $scope.users.password_confirmation) {
            $scope.user.push(this.users);
             Users.save({user: $scope.user}, function(){
             console.log(':)')
            }, function(error){
              console.log(error)
            });
            $scope.users = '';
          }
        };
    }]);
    
    App.config(['$routeProvider','$locationProvider','$httpProvider',
      function($routeProvider, $locationProvider, $httpProvider) {
        $routeProvider.
          when('/home', {
            templateUrl: 'views/main.html',
            controller: 'MainCtrl'
          }).
          otherwise({
            redirectTo: '/home'
          });
                  // use the HTML5 History API
            $locationProvider.html5Mode(true);
            $httpProvider.defaults.useXDomain = true;
    delete $httpProvider.defaults.headers.common["X-Requested-With"];
      }]);
    

    So i tried a lot solutions but no one fixed my.

  • akostadinov
    akostadinov almost 7 years
    @Trusislv1, also if you serve UI from same domain, protocol and port, you will not need this as the pre-flight OPTIONS requests would not be sent at all.