3

I have two APIs that I'm trying to mount in my Rails app-- one called 'v1' and another called 'twilio'. Each API will be composed of multiple files, so I want each to have its own folder. Inside my app/api directory, I have 2 folders--'v1' and 'twilio'--and a file called 'api.rb' that I am trying to use to mount the two api's. It's contents are:

module API
  class V1 < Grape::API
    prefix "api"
    format :json
    mount API::Root => '/v1'
  end

  class Twilio < Grape::API
    prefix "twilio"
    format :xml
    mount API::Twilio_API => '/twilio'
  end
end

In the 'v1' directory, I have a file called 'root.rb' that begins as follows:

module API
  class Root < Grape::API
    version 'v1', :using => :header
    ...

And in the 'twilio' directory, I have a file called 'twilio_api.rb' that begins as:

module API
  class Twilio_API < Grape::API
    version 'v1', :using => :header
    ...

My routes file has:

mount API::V1 => "/"
mount API::Twilio => "/"

When I start my rails server, I'm getting the error:

`load_missing_constant': Expected [My rails app]/app/api/v1/root.rb to define Root (LoadError)

I don't understand this, since root.rb certainly does define the Root class. Any help would be much appreciated.

Andrew
  • 2,425
  • 2
  • 24
  • 35

4 Answers4

7

In Grape you can mount multiple APIs in another one. That means you can have one "base" class for your APIs and mount all other into it.

Files Structure:

app/
  api/
    v1/
      v1_api.rb
    twilio/
      twilio_api.rb
    api.rb

app/api/api.rb:

require 'v1/v1_api'
require 'twilio/twilio_api'

module API
  class Base < Grape::API
    mount API::V1
    mount API::Twilio
  end
end

app/api/v1/v1_api.rb:

module API
  class V1 < Grape::API
    prefix "v1"
    format :json

    get :hello do
      { text: 'Hello from V1' }
    end
  end
end

app/api/twilio/twilio.rb:

module API
  class Twilio < Grape::API
    prefix "twilio"
    format :xml

    get :hello do
      { text: 'Hello from Twilio' }
    end
  end
end

config/routes.rb:

mount API::Base => '/api'

Restart your rails server and you're good to go. Also you should be easily able to autoload files from app/api/twilio and app/api/v1 directories, so you won't have to require them.

Marek Takac
  • 3,002
  • 25
  • 30
0

I think it is expecting your class name to be under the equivalent structure than the directory structure. Which would give you:

class API::V1::Root End

Or something in those lines.

(From my phone...)

jipiboily
  • 1,240
  • 10
  • 17
  • I tried changing my mount calls to follow the pattern 'mount ::API::V1::Root', and wrapping the 'Root' and 'Twilio' class definitions inside parent modules with the names 'V1' and 'TWILIO' respectively, in order to match the directory structure, but I'm still getting the same error. – Andrew May 02 '13 at 22:55
0

I had a similar error, and resolved it by requiring the files on top of the class. i.e.

require 'root'
require 'twilio'

in api.rb

In Grape API, there are instructions to autoload the file names, not sure if this has been done or will help you:

Place API files into app/api and modify application.rb.

config.paths.add "app/api", glob: "**/*.rb"
config.autoload_paths += Dir["#{Rails.root}/app/api/*"]
Xuwen
  • 231
  • 2
  • 3
0

Add this code in app/config/initializers/inflections.rb

ActiveSupport::Inflector.inflections(:en) do |inflect|
   inflect.acronym 'API'
 end
Yaroslavm
  • 1,762
  • 2
  • 7
  • 15