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
Related
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
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 am somewhat new to RoR,
I want to have a structured directory, because project may become big I don't want to have all controllers directly into controllers directory.
I would want something as
app/
controllers/
application_controller.rb
groupa/
athing_controller.rb
athing2_controller.rb
groupb/
bthing_controller.rb
However when I place in the routes.rb the following:
get 'athing', :to => "groupa/athing#index"
I get the following error on localhost:3000/athing/ :
superclass mismatch for class AthingController
Which is like:
class AthingController < ApplicationController
def index
end
end
Am I missing something?
Can I place subdirectories at all?
Try to use namespace instead:
In your routes:
namespace :groupa do
get 'athing', :to => "athing#index"
end
In your controller:
class Groupa::AthingController < ApplicationController
In browser:
localhost:3000/groupa/athing/
Modularity
When you put your controllers (classes) into a subdirectory, Ruby/Rails expects it to subclass from the parent (module):
#app/controllers/group_a/a_thing_controller.rb
class GroupA::AThingController < ApplicationController
def index
end
end
#config/routes.rb
get :a_thing, to: "group_a/a_thing#index" #-> url.com/a_thing
I've changed your model / dir names to conform to Ruby snake_case convention:
Use snake_case for naming directories, e.g. lib/hello_world/hello_world.rb
Use CamelCase for classes and modules, e.g class GroupA
Rails routing has the namespace directive to help:
#config/routes.rb
namespace :group_a do
resources :a_thing, only: :index #-> url.com/group_a/a_thing
end
... also the module directive:
#config/routes.rb
resources :a_thing, only: :index, module: :group_a #-> url.com/a_thing
scope module: :group_a do
resources :a_thing, only: :index #-> url.com/a_thing
end
The difference is that namespace creates a subdir in your routes, module just sends the path to the subdir-ed controller.
Both of the above require the GroupA:: superclass on your subdirectory controllers.
In config/routes.rb
namespace :namespace_name do
resources : resource_name
end
In app/controllers/
create a module name with your namespace_name, in that place your controllers
In that controller class name should be like
class namespace_name::ExampleController < ApplicationController
I tried to add namespace in my RoR project.
It works as expected:
controller:
class Dashboard::CategoriesController < ApplicationController
...some code
end
routes.rb
namespace "dashboard" do
resources :categories
end
but it doens'y work:
class Dashboard::UsersController < ApplicationController
...some code
end
class Dashboard::CardsController < ApplicationController
...some code
end
routes.rb:
namespace "dashboard" do
resources :users do
resources :cards do
member do
post 'review'
end
end
end
end
it throws an routing error: uninitialized constant CardsController
what's wrong?
Rails auto loads class if its name match file name. Error indicates that CardsController class is not loaded, so most probably you named your controller file wrongly. It should be app/controllers/dashboard/cards_controller.rb.
First of all, you'll be better making your routes more compacted:
#config/routes.rb
namespace :dashboard do
resources :users do
resources :cards do
post :review #-> domain.com/dashboard/users/:user_id/cards/1
end
end
end
The error it self will likely be caused by the way in which you're trying to call the controller. Typically, you'll receive errors with the namespace prepended to the class name (Dashboard::CardsController). In this instance, it just says CardsController.
You'll need to look at how you're calling the route.
Specifically, I presume you're using a form_for - which will build the route for you. If this is the case, you'll need to use the namespace within the form_for declaration itself:
<%= form_for [:dashboard, #user, #card], url: dashboard_user_cards_review(#user, #card) do |f| %>
I am trying to use namespaces to declare an api.
My routes.rb contains:
devise_scope :user do
namespace :api do
namespace :v1 do
match 'log_in', :to => 'token_authentications#log_in', :via => "post"
end
end
end
And my *token_authentications_controller.rb* looks like this:
class Api::V1::TokenAuthenticationsController < ApplicationController
...
def log_in
...
end
...
end
When I hit: api/v1/log_in I get:
Routing Error
uninitialized constant Api
So do I need to declare the namespace somewhere?
Rails expects namespaces to follow directory structure, unless I'm mistaken.
Given your class name for your controller, Api::V1::TokenAuthenticationsController, rails expects it to live in app/controllers/api/v1/token_authentications_controller.rb.
If you just move your controller to the correct folder, I think you should be fine.
You might also want to make sure to actually declare the namespace modules somewhere, like for instance refactoring your controller as such:
module Api
module V1
class TokenAuthenticationsController
...
end
end
end