routing error uninitialized constant API rails - ruby-on-rails

I have referred this link
to create my own api but facing an routing error since this is the first time am using namespace.
This is the controller I have
class API::IndexController < ApplicationController
def index
#clients = Client.all
respond_to do |format|
format.json
end
end
end
my route has
namespace :api do
resources :index
end
Here is my inflection.rb
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.acronym 'API'
end
Once i finish it I tried localhost:3000/api/index.json but throwing error as
Routing Error
uninitialized constant API
Can anyone help.

Even if this question is pretty old...
I had the same problem and my solution was to rename the api-folders (in app/controllers and app/views) from "API" (full caps) to "api" (all lower case)
Hope this helps

You must have the same name in your class same as your namespace. Try this:
class Api::IndexController < ApplicationController
def index
#clients = Client.all
respond_to do |format|
format.json
end
end
end
routes:
namespace :api do
resources :index
end

If you are defining your namespace for IndexController as API then in your routes.rb it should be written as
namespace :a_p_i do
resources :index
end
Otherwise, if you want to use what you have written in your routes file then just change the namespace for IndexController form API to Api . For Ex : Api::IndexController

To solve this add the following file
#./spec/support/api/helper.rb
module ApiHelper
include Rack::Test::Methods
def app
Rails.application
end
end
RSpec.configure do |c|
c.include ApiHelper, :type => :api
end
Then include it in spec_helper.rb
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
Read https://gist.github.com/alex-zige/5795358 for more info.

This is a somewhat old question, but my experience could still be useful.
I found my problem was because of a typo in the file name, I had a class named ApiFooController and the file was named api_foo_contoller.rb (notice the missing 'n' in the file name).
So it seems this error comes down to one general problem, and it's failig to correctly follow the naming conventions.
My guess is the controller was probably placed under controller/ path instead of controller/api and also the namespace should've been Api, not API (Not sure if adding API as an Acronym does the trick, I've never tried it.

Related

Can't find a route with an underscore or doesn't treat it properly

I have this in routes:
Rails.application.routes.draw do
namespace :api do
namespace :v3_4 do
# .....
And the controller app/controllers/api/v3_4/base_controller
module Api
module V3_4
class BaseController < ApplicationController
# ......
end
end
end
And app/controllers/api/v3_4/another_controller
module Api
module V3_4
class AnotherController < ApplicationController
end
end
end
rake routes:
Prefix Verb URI Pattern Controller#Action
api_v3_4_test GET /api/v3_4/test(.:format) api/v3_4/base#test
api_v3_4_one GET|OPTIONS /api/v3_4/one(.:format) api/v3_4/another#one
api_v3_4 GET|OPTIONS /api/v3_4/two/:id(.:format) api/v3_4/another#two
And yet for this request I get Routing Error Uninit Constant uninitialized constant Api::V34
Note there's no underscore in the error message.
But my project there's no line V34 at all, neither v34, only v3_4 and V3_4
Rails inflects _ to be a word separator, so it searches for Api::V34 you can change that behavior by editing config/initializers/inflections.rb:
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.acronym 'V3_4'
end
Moreover, if you want to change Api namespace to API, since it's an acronym, you can do it there as well:
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.acronym 'V3_4'
inflect.acronym 'API'
end
More info: http://api.rubyonrails.org/classes/ActiveSupport/Inflector/Inflections.html
The Ruby-Style-Guide helped me a lot to clarify these questions. Please see the naming section.

Unable to autoload constant in API Controller

I'm trying to setup a RoR API but I'm hitting a few roadbump along the way. After tiresome coding to get the database setup right I'm hitting an error that doesn't quite make sense to me (I'm new to RoR)
Unable to autoload constant Api::V1::SubmissionsController, expected ./app/controllers/api/v1/submissions_controller.rb to define it
I'm not quite sure what this error means and my interwebs searches are coming up empty on a clear answer. I'm hoping any of you can help me here.
Routes
Rails.application.routes.draw do
namespace :api, :defaults => {:format => :json} do
namespace :v1 do
get "/submissions", to: "submissions#index"
end
end
end
submission.rb
class Submission < ActiveRecord::Base
end
submissions_controller.rb
class API::V1::SubmissionsController < ApplicationController
def index
#submissions = Submission.all
render json: #submissions, status: :ok
end
end
Your file contains:
class API::V1::SubmissionsController < ApplicationController
Rails expects:
class Api::V1::SubmissionsController < ApplicationController
What does your folder structure look like for app/controllers & app/views? Depending on how these files were generated, by "rails generate" or manually created, if you namespace, the folder structure has to match in controllers and views directories.
app/controllers/api/v1
app/views/api/v1

Ruby on Rails rooting error

Im trying to create simple Ruby on Rails REST API.
app/controllers/api/vi/product_controller.rb
module Api
module V1
class ProductController < ApplicationController::API
def index
render json: {message: 'Welcome!'}
end
end
end
end
config/routes.rb
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
get '/product', to: 'product_controller#index', as: 'product'
end
end
end
When I run project on localhost, I get uninitialized constant Api::V1::ApplicationController routing error. Can anyone help to such Ruby on Rails newbie as I am?
you just need to create a folder inside controllers called api and a v1 folder inside api.
You should provide all the controllers inside v1 folder.
In your app/controllers/api/v1/product_controller.rb
class Api::V1::ProductController < ApplicationController
def index
render json: {message: 'Welcome!'}
end
end
In your routes:
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
get '/product', to: 'product_controller#index', as: 'product'
end
end
end
you nested the route, so it should be '/api/v1/product`
if you run rake routes from your console, you will get a list of all available routes.
for more information about routing and nested routes, have a look at rails guides
change this and try:
module Api
module V1
class ProductController < ApplicationController
def index
render json: {message: 'Welcome!'}
end
end
end
end

Rails 4.1: Creating routes by calling method in controller

I want to create a method that, when called from a controller, will add a nested resource route with a given name that routes to a specific controller. For instance, this...
class Api::V1::FooController < ApplicationController
has_users_route
end
...should be equivalent to...
namespace :api do
namespace :v1 do
resources :foo do
resources :users, controller: 'api_security'
end
end
end
...which would allow them to browse to /api/v1/foo/:foo_id/users and would send requests to the ApiSecurityController. Or would it go to Api::V1::ApiSecurityController? It frankly doesn't matter since they're all in the same namespace. I want to do it this way because I want to avoid having dozens of lines of this:
resources :foo do
resources :users, controller: 'api_security'
end
resources :bar do
resources :users, controller: 'api_security'
end
Using a method is easier to setup and maintain.
I'm fine as far as knowing what to do once the request gets to the controller, but it's the automatic creation of routes that I'm a little unsure of. What's the best way of handling this? The closest I've been able to find is a lot of discussion about engines but that doesn't feel appropriate because this isn't separate functionality that I want to add to my app, it's just dynamic routes that add on to existing resources.
Advice is appreciated!
I ended up building on the blog post suggested by #juanpastas, http://codeconnoisseur.org/ramblings/creating-dynamic-routes-at-runtime-in-rails-4, and tailoring it to my needs. Calling a method from the controllers ended up being a bad way to handle it. I wrote about the whole thing in my blog at http://blog.subvertallmedia.com/2014/10/08/dynamically-adding-nested-resource-routes-in-rails/ but the TL;DR:
# First draft, "just-make-it-work" code
# app/controllers/concerns/user_authorization.rb
module UserAuthorization
extend ActiveSupport::Concern
module ClassMethods
def register_new_resource(controller_name)
AppName::Application.routes.draw do
puts "Adding #{controller_name}"
namespace :api do
namespace :v1 do
resources controller_name.to_sym do
resources :users, controller: 'user_security', param: :given_id
end
end
end
end
end
end
end
# application_controller.rb
include UserAuthorization
# in routes.rb
['resource1', 'resource2', 'resource3'].each { |resource| ApplicationController.register_new_resource(resource) }
# app/controllers/api/v1/user_security_controller.rb
class Api::V1::UserSecurityController < ApplicationController
before_action :authenticate_user!
before_action :target_id
def index
end
def show
end
private
attr_reader :root_resource
def target_id
# to get around `params[:mystery_resource_id_name]`
#target_id ||= get_target_id
end
def get_target_id
#root_resource = request.fullpath.split('/')[3].singularize
params["#{root_resource}_id".to_sym]
end
def target_model
#target_model ||= root_resource.capitalize.constantize
end
def given_id
params[:given_id]
end
end

What are the best practices for designing a RESTful public API on Rails?

Rails comes with RESTful resources out of the box, but do you use those for your actual public API? If so, how would you accomplish versioning of your API i.e. example.com/api/v2/foo/bar?
Typically, APIs for my applications are indeed built on the same resources that make up the HTML interface. For some (not me), that might be just using the code that comes out of the scaffold generator—but regardless of whether I write it custom or let the generator handle it, there are very few instances where I expose resources only to the programmatic API and not to the end user view.
Versioning hasn't been a problem for the applications I've built so far, but I can think of two ways to implement it.
1) You could add routes with the prefix 'v1,' 'v2,' etc., that set a parameter that you can then access in the controller to specify the processing to occur:
in routes.rb:
map.resources :posts, :path_prefix => '/:version'
in posts_controller.rb
class PostsController < ApplicationController
def index
respond_to do |format|
format.xml do
if params[:version] == 'v1'
# ...
else
# ...
end
end
end
end
end
2) You might also consider adding a custom response format for each version
in initializers/mime_types.rb
Mime::Type.register_alias "application/xml", :v1
Mime::Type.register_alias "application/xml", :v2
in posts_controller.rb
class PostsController < ApplicationController
def index
respond_to do |format|
format.v1 do
# ...
end
format.v2 do
# ...
end
end
end
end
The former would give you URLs like example.com/v1/posts.xml and example.com/v2/posts.xml; the latter would give you URLs like example.com/posts.v1 and example.com/posts.v2

Resources