Ameya Vichare Ameya Vichare - 4 months ago 59
JSON Question

Deploying a Rails API on either Heroku/AWS Elastic Beanstalk

I'm trying to pair a mobile client with a REST API so that I get JSON data which I can display in the app. I'm following Apis on Rails by Abraham Kuri Vargas. In the API I have created a subdomain as well as some versioning, so the controller files are in app/controllers/api/v1. The API returns desired JSON data when I run it locally. The problem I'm facing is whenever I deploy the API onto Heroku/AWS it will show "Application not found". Is it that the remote server isn't finding its way into app/controllers/api/v1? Is there any fix for a problem like this because even in the book the author has written "Due to the structure of the application we are not going to deploy the app to any server". I'm really stuck on this problem for a long time and would love any suggestions!

app/controllers/api/v1/users_controller.rb

class Api::V1::UsersController < ApplicationController
respond_to :json

def show
respond_with User.find(params[:id])
end

def create
user = User.new(user_params)
if user.save
render json: user, status: 201, location: [ :api,user ]
else
render json: { errors: user.errors }, status: 422
end
end

def update
user = User.find(params[:id])
if user.update(user_params)
render json: user, status: 200, location: [ :api,user ]
else
render json: { errors: user.errors }, status: 422
end
end

def destroy
user = User.find(params[:id])
user.destroy
head 204
end

private
def user_params
params.require(:user).permit(:email,:password,:password_confirmation)
end
end


config/routes.rb

require 'api_constraints'

Rails.application.routes.draw do

devise_for :users
namespace :api, defaults: { format: :json }, constraints: { subdomain: 'api' }, path: '/' do
scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
#resources
resources :users, :only => [:show, :create, :update, :destroy]
end
end
end


Output, when I run localhosts://3000/users/1 locally

{"id":1,"email":"example@marketplace.com","created_at":"2016-06-09T05:36:06.606Z","updated_at":"2016-06-09T05:36:06.606Z"}

Heroku server logs when I run petoye.herokuapp.com/users/1

Started GET "/users/1" for 120.60.22.244 at 2016-06-12 06:43:36 +0000

ActionController::RoutingError (No route matches [GET] "/users/1"):

vendor/bundle/ruby/2.2.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/debug_exceptions.rb:21:in
call'

vendor/bundle/ruby/2.2.0/gems/railties-4.2.6/lib/rails/rack/logger.rb:38:in
call_app'

vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.6/lib/active_support/tagged_logging.rb:68:in
block in tagged'

vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.6/lib/active_support/tagged_logging.rb:68:in
tagged' vendor/bundle/ruby/2.2.0/gems/railties-4.2.6/lib/rails/rack/logger.rb:20:in
call'

vendor/bundle/ruby/2.2.0/gems/rack-1.6.4/lib/rack/methodoverride.rb:22:in
call'

vendor/bundle/ruby/2.2.0/gems/rack-1.6.4/lib/rack/runtime.rb:18:in
call'

2016-06-12T06:43:36.946702+00:00 app[web.1]: vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.6/lib/active_support/cache/strategy/local_cache_middleware.rb:28:in
call'

vendor/bundle/ruby/2.2.0/gems/puma-3.4.0/lib/puma/server.rb:569:in
handle_request'

vendor/bundle/ruby/2.2.0/gems/puma-3.4.0/lib/puma/thread_pool.rb:114:in
block in spawn_thread'

Answer

The problem with heroku is that if you don't pay for a domain, and just use the base service, it will assign a subdomain for your app. So all I needed to do was to redirect heroku to a custom url such as api.any_domain.com.

An easier alternative would be to override the constraints for the api on the routes.rb file:

  namespace :api, defaults: { format: :json }, path: '/api'  do

You will now be able to see the API under http://herokuapp.com/api/any_endpoint