Unable to autoload constant in API Controller - ruby-on-rails

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

Related

Rails routing with namespaces and nested routes

I have an email_template model that has a nested resource moves to handle moving an email_template from one folder to another.
However, I want to namespace these actions in a :templates namespace because I have several other resources that are template items as well.
Since I'm namespacing, I don't want to see templates/email_templates/:id in the URL, I'd prefer to see templates/emails/:id.
In order to accomplish that I have the following:
# routes.rb
namespace :templates do
resources :emails do
scope module: :emails do
resources :moves, only: [:new, :create]
end
end
end
Everything works fine when I do CRUD actions on the emails, since they are just using the :id parameter. However, when I use the nested moves, the parent ID for the emails keeps coming across as :email_id and not :email_template_id. I'm sure this is the expected behavior from Rails, but I'm trying to figure out how the parent ID is determined. Does it come from the singular of the resource name in the routes, or is it being built from the model somehow?
I guess it's ok to use templates/emails/:email_id/moves/new, but in a perfect world I'd prefer templates/emails/:email_template_id/moves/new just so developers are clear that it's an email_template resource, not a email.
# app/controllers/templates/emails_controller.rb
module Templates
class EmailsController < ApplicationController
def show
#email_template = EmailTemplate.find(params[:id])
end
end
end
# app/controllers/templates/emails/moves_controller.rb
module Templates
module Emails
class MovesController < ApplicationController
def new
# Would prefer to reference via :email_template_id parameter
#email_template = EmailTemplate.find(params[:email_id])
end
def create
#email_template = EmailTemplate.find(params[:email_id])
# Not using strong_params here to demo code
if #email_template.update_attribute(:email_tempate_folder_id, params[:email_template][:email_template_folder_id])
redirect_to some_path
else
# errors...
end
end
end
end
end
You could customize the parameter as:
resources :emails, param: :email_template_id do
...
end

running a simple rails-api project returns ActiveRecord::ConnectionNotEstablished error

This might be a really stupid question. But I am starting to create a rails API and created a skeleton api with one controller index action which returns a static json.
Here is the sequence of steps I followed:
rails-api new my-app
My gemfile has:
gem 'rails', '4.1.8'
My routes are as follows:
MyApp::Application.routes.draw do
namespace :api, defaults: {format: 'json'} do
namespace :v1 do
resources :projects
end
end
end
here is my controller:
module Api
module V1
class ProjectsController < ApplicationController
def index
render json: {message: 'Resource not found'}, status: 404
end
end
end
end
Here is my model which has nothing:
class Project < ActiveRecord::Base
end
So when I try run the app rails s and go to:
localhost:3000/certificates/ or localhost:3000/api/v1/certificates
I get the following error:
ActiveRecord::ConnectionNotEstablished
Eventually I am going to add a database and retrieve results from a real table, but I was wondering shouldn't my above code return the json "Resource not found" instead of trying to connect to active record.
Does it always require an activerecord connection? I am trying to understand how rails-api works.
When you run the server ActiveRecord gets loaded automatically, and it will whine since it wants a db to connect to. Ìf you really need to, you can "deactivate" ActiveRecord on startup by following this answer.

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

routing error uninitialized constant API 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.

Rails routing and controller modules -namespacing?

I have trouble creating a module for my controller, and getting my routes to point to that module within the controller.
Getting this error:
Routing Error
uninitialized constant Api::Fb
So, this is how my routes are set up:
namespace :api do
namespace :fb do
post :login
resources :my_lists do
resources :my_wishes
end
end
end
In my fb_controller i want to include modules that will give me paths like this:
/api/fb/my_lists
This is some of my fb_controller:
class Api::FbController < ApplicationController
skip_before_filter :authenticate_user!, :only => [:login]
include MyLists # <-- This is where i want to include the /my_lists
# namespace(currently not working, and gives me error
# mentioned above)
def login
#loads of logic
end
end
The MyLists.rb file(where i define a module) is in the same directory as the fb_controller.rb.
How can i get the namespacing to point to my module inside of the fb_controller, like /api/fb/my_lists ?
The namespace you have set up is looking for a controller class that looks like this
class Api::Fb::MyListsController
If you want to have a route that looks like /api/fb/my_lists but you want to still use the FbController instead of having a MyListsController you need to set up your routes to look like this
namespace :api do
scope "/fb" do
resources :my_lists, :controller => 'fb'
end
end
In my opinion, instead of including a module MyLists in your FbController seems kind of awkward.
What I would probably do is have a module FB with a generic FbController then have MyListsController < FbController. Anyway, this is beyond the scope of your question.
The above should answer for your needs.
EDIT
From your comments, and my assumptions on what you're trying to do this is a small example:
config/routes.rb
namespace :api do
scope "/fb" do
post "login" => "fb#login"
# some fb controller specific routes
resources :my_lists
end
end
api/fb/fb_controller.rb
class Api::FbController < ApiController
# some facebook specific logic like authorization and such.
def login
end
end
api/fb/my_lists_controller.rb
class Api::MyListsController < Api::FbController
def create
# Here the controller should gather the parameters and call the model's create
end
end
Now, if all you want to create a MyList Object then you could just do the logic directly to the model. If, on the other hand, you want to handle some more logic you'd want to put that logic in a Service Object that handles the creation of a MyList and its associated Wishes or your MyList model. I would probably go for the Service Object though. Do note, the service object should be a class and not a module.
In your example, Fb isn't a namespace, it's a controller. The namespace call is forcing your app to look for a Fb module that doesn't exist. Try setting up your routes like this:
namespace :api do
resource :fb do
post :login
resources :my_lists do
resources :my_wishes
end
end
end
You can optionally define a new base controller for the API namespace:
# app/controllers/api/base_controller.rb
class Api::BaseController < ApplicationController
end
If you do so, your other controllers can inherit from this:
# app/controllers/api/fb_controller.rb
class Api::FbController < Api::BaseController
end
Running rake routes should give you an idea of how your other controllers are laid out. Just a warning - it's generally not recommended to have resources nested more than 1 deep (you're going to end up with complex paths like edit_api_fb_my_list_my_wish_path). If you can architect this in a simpler way, you'll probably have an easier time of this.

Resources