Sending an Angular post request with parameter to Rails API Sending an Angular post request with parameter to Rails API angularjs angularjs

Sending an Angular post request with parameter to Rails API


I finally made it work.

I will explain all my config in Angular and Rails 4 as I would have liked to read it.

Angular

  1. app.js:

    angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'myApp.controllers', 'myApp.i18n', 'demo']).config(['$routeProvider', '$httpProvider', function($routeProvider, $httpProvider) {$httpProvider.defaults.useXDomain = true;delete $httpProvider.defaults.headers.common["X-Requested-With"];           

    }]);

Note: Of course, you donĀ“t need to include all my modules.

  1. In my view:

    <form novalidate="" name="createBusinessForm" ng-submit="setBusinessInformation()" class="css-form">                    <label>* {{'BUSINESS_NAME' | translate}}</label>        <input type="text" name="name" ng-model="business.name" class="input-xxlarge input-height-large" placeholder="{{'BUSINESS_NAME_PLACEHOLDER' | translate}}" required maxlength="80">        <span ng-show="createBusinessForm.name.$dirty && createBusinessForm.name.$error.required" class="text-error">Mandatory field.</span>        <label>* {{'ID' | translate}}</label>            <input type="text" ng-model="business.cif_nif" class="input-xlarge input-height-large" placeholder="{{'BUSINESS_ID_PLACEHOLDER' | translate}}" required maxlength="60">                <label>* {{'ADDRESS' | translate}}</label>    

Note: You can define as many fields as you need and with data bingind assign the values to an object.

  1. in my controller:

    $scope.createBusiness = function() {        $scope.business.type = $scope.type;         $scope.business.plan = $scope.plan;             $scope.business = Business.save($scope.business);                   $location.path('/user-dashboard');                                  }; 

Note: All the attributes you need to send in the post request. Apart from the form, you can assign some new attributes to the object before sending to Rails API. We will use a service with a resource object to send the POST request.

  1. In my service:

    .factory('Business',

      function($resource){              var businesses =     $resource('http://127.0.0.1\\:3000/:business', {business:'businesses'}, {              query: {method:'GET', isArray: true},        save: {method:'POST', isArray: false}     });             return businesses;             }

    );

Note: I have a GET request to get the business from DB through Rails API and the POST one.

Rails 4

IMPORTANT

  1. routes.rb

    match "/businesses" => "application#index", via: :options  

Note: New entry to match the OPTIONS request the Angular server will send to pre-negociate the start of sending the POST request.

  1. application_controller.rb

    class ApplicationController < ActionController::Basebefore_filter :set_headersdef index  puts "Do nothing."  render nothing: trueenddef set_headers  puts 'ApplicationController.set_headers'  if request.headers["HTTP_ORIGIN"]       # better way check origin  # if request.headers["HTTP_ORIGIN"] && /^https?:\/\/(.*)\.some\.site\.com$/i.match(request.headers["HTTP_ORIGIN"])    headers['Access-Control-Allow-Origin'] = request.headers["HTTP_ORIGIN"]    headers['Access-Control-Expose-Headers'] = 'ETag'    headers['Access-Control-Allow-Methods'] = 'GET, POST, PATCH, PUT, DELETE, OPTIONS, HEAD'    headers['Access-Control-Allow-Headers'] = '*,x-requested-with,Content-Type,If-Modified-Since,If-None-Match,Auth-User-Token'    headers['Access-Control-Max-Age'] = '86400'    headers['Access-Control-Allow-Credentials'] = 'true'  endend               end
  2. My Rails controller

    def create  puts 'Businesses_controller.create!!!!!'  puts business_params.inspect  # business_type object is recovered from db  businessTypeName = params[:type]      businessType = BusinessType.where(:name => businessTypeName).first  ...end

Note: Here do whatever you need...


We had the same problem and took a similar but hopefully simpler/quicker/more flexible approach.

The quick rundown of what I did was use to the ruby library "rack-cors" (https://github.com/cyu/rack-cors) to manage all the CORS headers.

This means I didn't have to stick a bunch of hardcoded header name/values in my code.

The big benefit for me was that this takes care of both simple CORS requests (GET request and response) and preflighted requests that use OPTION requests (OPTIONS request and response and then POST request and response).

Here are the quick steps that I followed:

  1. gem install rack-cors
  2. add the following to Gemfile:

    gem 'rack-cors', :require => 'rack/cors'
  3. run "bundle install", which will update Gemfile.lock

  4. edit config/application.rb to add the following block:

    config.middleware.insert_before "ActionDispatch::Static", "Rack::Cors", :debug => true, :logger => Rails.logger do  allow do    origins '*'    resource '*',      :headers => :any,      :methods => [:get, :post, :delete, :put, :options],      :max_age => 0  endend

Now in my case, I just wanted to open this up to any host, but you could be more restrictive. You can also limit headers and http methods too.

See more details on readme at the github page: https://github.com/cyu/rack-cors(The rack-cors author has example rails apps under examples/rails3 and examples/rails4)