I have Rails 5 API project for controlling user tasks and I have the following error but not always for the same controller and route.
ActionController::RoutingError: uninitialized constant Api::V1::ApiController
I describe you a little bit my project to explain in more detail the error.
App structure
Routes
scope module: 'api' do
namespace :v1 do
# => Login routes
scope module: 'login' do
match 'login', to: 'sessions#login', as: 'login', via: :post
end
# => Team routes
scope module: 'team' do
# => no admin routes
resources :tasks, except: [:index] do
collection do
match ':view', to: 'tasks#index', as: 'tasks', via: [:get, :post]
end
end
end
end
end
API Controller
module Api
class ApiController < ApplicationController
def respond_with_errors(object)
render json: {errors: ErrorSerializer.serialize(object)}, status: :unprocessable_entity
end
end
end
Team Controller
module Api::V1
class Team::TeamController < ApiController
Tasks Controller
module Api::V1
class Team::TasksController < Team::TeamController
Login Controller
module Api::V1
class Login::LoginController < ApiController
Sessions Controller
module Api::V1
class Login::SessionsController < Login::LoginController
When I execute login route and after tasks route, I get the error in last route and all the routes in team module. If I change the project and save it (only one blank space) and then I execute tasks route and after login route, I get the error in last route and all the routes in login module.
It doesn't have any sense...
Rails server in this errors
You should be using the right constant while inheriting - ::Api::ApiController:
module Api::V1
class Team::TeamController < ::Api::ApiController
because otherwise it is searching for Api::V1::ApiController, but should search for Api::ApiController
Right now you have Api::ApiController.
Your app/controllers/api/v1/api_controller.rb is missing V1 in namespace
module Api::V1
class ApiController < ApplicationController
..
end
end
UPDATE
If your ApiController is outside V1 folder then you should do
module Api::V1
class Team::TeamController < ::Api::ApiController
Related
I'm trying to add a namespace to my 'Category' controller and resource.
So the first thing I did was to move the categories_controller.rb to app/controllers/api/v1/categories_controller and the category_resource.rb to app/resources/api/v1/
And then I redeclared these artifacts as following:
Controller
module Api
module V1
class CategoriesController < ApplicationController
#before_action :doorkeeper_authorize!
end
end
end
Resource
module Api
module V1
class CategoryResource < JSONAPI::Resource
attribute :name
end
end
end
And in routes.rb I moved the categories route to
namespace :api do
namespace :v1 do
jsonapi_resources :categories
end
end
I already got different erros trying to solve this issue. To the current configuration, this is the error I get:
JSONAPI: Could not find resource 'categories'. (Class CategoryResource not found) (NameError)
What am I doing wrong?
Based on the documentation here (https://github.com/cerebris/jsonapi-resources) you should not move the resource.
And it should not be in the modules.
Your code looks fine - I have something similar with jsonapi-resources 0.7.0:
class Api::V1::UsersController
...
class Api::V1::UserResource < BaseResource
...
namespace :api do
namespace :v1 do
jsonapi_resources :users do
jsonapi_relationships
end
is it possible your rails load path is trying to load the api/v1 directory directly rather than treating it as a module subfolder?
I have a class called Device. It has a model device.rb
I have set the routing up so that the same controller is called from two different paths. i.e. the paths:
/driver_api/v1/devices
and
/sender_api/v1/devices
both call the following controller:
/user_api/v1/devices
In my routes.rb I have:
namespace :driver_api do
namespace :v1 do
resources :devices, :only => [:create], controller: '/user_api/v1/devices'
end
end
namespace :sender_api do
namespace :v1 do
resources :devices, :only => [:create], controller: '/user_api/v1/devices'
end
end
Now, in my devices controller, I'm trying to call a Device class method. i.e. in my controller:
class UserApi::V1::DevicesController < ApplicationController
Devise.method_name(input)
end
But i get an error:
uninitialized constant UserApi::V1::DevicesController::Device
Why am I getting this error?
Because you wrote Devise and not Device that could be a good reason.
If that is just a typpo from the question, here's another alternative.
Sometimes there's some kind of naming problem when the classes are defined in the way you did (I ignore the reason why that happens)
Try to decompose the class scoping by defining the modules:
module UserApi
module V1
class DevicesController < ApplicationController
# rest
end
end
end
Hi I'm getting this error
Circular dependency detected while autoloading constant
Subdomain::Settings::ThemesController
in my Rails 4.0 app whenever I try to access the stated controller. In fact I get similar errors for any of the other controllers name-spaced with the themes controller.
I have the following controllers name-spaced under Settings which itself is name-spaced under Subdomain.
Are these controllers defined correctly? Can anyone spot why this circular dependency error is cropping up?
# app/controllers/subdomain/settings/security_controller.rb
module Subdomain
class Settings::SecurityController < BaseController
def edit
...
end
end
end
# app/controllers/subdomain/settings/themes_controller.rb
module Subdomain
class Settings::ThemesController < BaseController
def edit
...
end
end
end
# app/controllers/subdomain/settings/profiles_controller.rb
module Subdomain
class Settings::ProfilesController < BaseController
def edit
...
end
end
end
# app/controllers/subdomain/base_controller.rb
class Subdomain::BaseController < ApplicationController
...
end
And the following routes configuration
MyApp::Application.routes.draw do
constraints(Constraints::SubdomainRequired) do
scope :module => :subdomain do
namespace 'settings' do
root to: 'security#edit'
resource :theme, only: [:create, :edit, :update], :controller => 'themes'
resource :profile, only: [:edit, :update], :controller => 'profiles'
resource :security, only: [:edit, :update], :controller => 'security'
end
end
end
end
The solution was I needed to rewrite each controller like so
module Subdomain
module Settings
class ProfileController
...
instead of
module Subdomain
class Settings::ProfileController
Attempting to create an API using doorkeeper. When I sign into my account and the session user is authenticated and access my API on
http://localhost:3000/api/v1/trials
I get a routing error page saying "uninitialized constant TrialsController" and a rake routes listing. Including:
trials_path GET /api/v1/trials(.:format) trials#index
I am using rails version 4.0.3, ruby 2.0.0. This is my config/routes.rb file:
MyApp::Application.routes.draw do
devise_for :users
use_doorkeeper :scope => 'oauth2' do
end
root :to => 'welcome#index'
scope 'api' do
scope 'v1' do
resources :trials
end
end
end
My app/ dir contains:
app/
controllers/
application_controller.rb
welcome_controller.rb
api/
v1/
trials_controller.rb
My trials_controller.rb is:
module Api::V1
class TrialsController < ::ApplicationController
doorkeeper_for :all
def index
#trials = Trials.all
end
def show
...
end
...
end
end
UPDATE:
When I change the routes.rb to namespace the trails controller like so:
namespace :api do
namespace :v1 do
resources :trails
end
end
I get a "no route matches" error when attempting to access:
http://localhost:3000/api/v1/trials(.json)
(With or without the extension.)
I have also added to trials#index:
def index
#trials = Trials.all
respond_to do |format|
format.json { render :json => #trials }
format.xml { render :xml => #trials }
end
end
Also with no luck.
I'm not sure how it would play out against doorkeeper but I have a similar API structure in an app. I have the following in my routes (matching what Sergio notes)
namespace :api, defaults: {format: 'json'} do
namespace :v1 do
resources :api_controller_1
resources :api_controller_2
end
end
And here's how I build my API classes:
module Api
module V1
class ApiNamedController < ApplicationController
# code
end
end
end
I added an Admin namespace to my app so when logging in to the administration area, it would have to be like this: admin/websites and admin/page/8
So this is what I have in my routes.rb
namespace :admin do |admin|
match '/' => 'dashboard#index'
resources :websites
resources :pages
resources :sessions
get 'login' => 'sessions#new', :as => 'login'
get 'logout' => 'sessions#destroy', :as => 'logout'
end
I have admin_controller.rb in app/controllers directory.
class Admin::BaseController < ApplicationController
protect_from_forgery
include UrlHelper
...
I created an admin directory inside app/controllers. So I have this inside app/controllers/admin/websites_controller.rb
class Admin::WebsitesController < ApplicationController
Some other answers suggested class Admin::WebsitesController < Admin::BaseController, but that never worked for me. If I'm wrong please let me know.
So then in my layout file (app/views/layouts/application.html.erb) I have links like this one edit_admin_website_path(#website) that give me routing errors Routing Error No route matches {:action=>"edit", :controller=>"admin/websites"} Whyyyy?! :(
Add a file named application_controller.rb in the admin directory with this content:
class Admin::ApplicationController < ApplicationController
end
Then, for each controller on this directory, extend the Admin::ApplicationController class.
Did you try this?
admin_edit_website_path(#website)
Rails namespaces rely on folder structure for loading the right classes. You should structure it like this:
app/controllers
admin_controller.rb # class AdminController < ApplicationController
app/controllers/admin
websites_controller.rb # class Admin::WebsitesController < AdminController
The AdminController should be defined outside the admin folder. If put it in there you'd have to refer to it as Admin::AdminController which is a little odd. In fact, you could call it AdminNamespaceController to be clear.
You can also use rails generate which will set things up for you in the expected places, although I don't think it creates the namespace base class for you to inherit from.