Unable to autoload constant API Controller in Rails 4 model in module - ruby-on-rails

I'm trying to create an api controller for a model defined in a module
Model class:
module Reports
class Report < ActiveRecord::Base
end
end
Api controller:
class API::V2::ReportsController < API::V2::BaseController
end
Route:
namespace :api, defaults: { format: :json } do
namespace :v2 do
resources :reports
end
end
The error I get when try to call api/v2/reports is:
LoadError (Unable to autoload constant Report, expected /.../app/models/reports/report.rb to define it):
Is there a way to solve this, making the api controller look for Reports::Report instead of Report?

Your controller needs to include Reports somehow:
module Api
module V2
module Reports
class Report < API::V2::BaseController
your controller actions
end
end
end
end
Apart from that, I think it will be confusing if you use Reports::Report?

Related

Rails 5 - How to Have Controllers inside Subfolder?

I have a subfolder api in my controllers folder.
So when I call POST "/api/auth" I would like the program to get there using rails conventions.
I.E. I don't want to write the route for each call, but to use rails "patent" that makes rails go to CRUD actions understanding the PUT, POST, GET by itself.
So in my routes.rb I have:
namespace :api do
resources :debts, :auth
end
But when I POST (or GET) with localhost:3000/api/auth I get:
ActionController::RoutingError (uninitialized constant Api::AuthController)
What am I missing?
Please note that I also need to have many controllers inside the subfolder. Is there a short match for all?
You have to put your controller in a sub folder too en then do e.g.
# /app/controllers/api/debts_controller.rb
module Api
class DebtsController < ApiController
end
end
# /app/controllers/api/auth_controller.rb
module Api
class AuthController < ApiController
end
end
Then in base controller folder:
# /app/controllers/api_controller.rb
class ApiController < ApplicationController
end
You need to namespace the class also in order to get this working.
The following 2 ways can be used:
module Api
class AuthController < ApplicationController
# Your controller code here
end
end
class Api::AuthController < ApplicationController
# Your controller code here
end
If you have some code that needs to be run for every controller inside the Api namespace, you can make an Api base controller, but it's not necessary.

Route not find - Rails

Rails 3.2
In my controllers/admin/accounts_receivables_contoller.rb, I have:
class Admin::AccountsReceivables < Admin::ApplicationController
def index
...
end
and in one of the views, I have:
= link_to admin_accounts_receivables_path
In my config/routes.rb, I have:
namespace :admin do
resources :accounts_receivables do
collection do
get 'admin_report'
get 'customer_report'
post 'process_invoices'
end
end
end
rake routes, produces:
admin_accounts_receivables GET admin/accounts_receivables(.:format) admin/accounts_receivables#index
However, when I click on the link, I get (in the browser, but no entry in the log file):
uninitialized constant Admin::AccountsReceivablesController
I do not have a corresponding AccountsReceivable model, as I don't need it.
Any ideas?
The class should be named AccountsReceivablesController and you should nest the class explicitly instead of using the scope resolution operator so that it has the correct module nesting:
module Admin
class AccountsReceivablesController < ApplicationController
def index
# ...
end
end
end
When you use the scope resolution operator class Admin::AccountsReceivablesController - the module nesting is resolved to the point of definition which is Main (the global scope) and not Admin. For example:
module Admin
FOO = "this is what we expected"
end
FOO = "but this is what we will actually get"
class Admin::AccountsReceivablesController < Admin::ApplicationController
def index
render plain: FOO
end
end
See The Ruby Style Guide - namespaces.
class Admin::AccountsReceivables < Admin::ApplicationController
should be...
class Admin::AccountsReceivablesController < Admin::ApplicationController

LoadError (Unable to autoload constant Api::V1::UsersController)

I'm using Rails 5 and I'm getting this error when calling a method in my Api. The thing is, the error only happens sometimes.
LoadError (Unable to autoload constant Api::V1::UsersController, expected /home/user/projects/project-name/app/controllers/api/v1/users_controller.rb to define it):
Relevant part of routes.rb:
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
resources :users
end
end
end
Relevant part of the controller:
class Api::V1::UsersController < ApplicationController
I'm clueless of whats wrong, google a lot but couldn't find a solution.
Have you tried adding to the top of your controller
module Api
module V1
class className < ApplicationController
....
end
end
end
This should follow your directory structure.

superclass mismatch for class usercontroller

I have created API in rails 5.
I am getting error superclass mismatch for class UsersController.
My controller:
module Api
module V1
class UsersController < ApplicationController
def index
users = User.Order('created_at DESC')
render json: {status:"SUCCESS", message:"Load Users", data:users}, status: :ok
end
def create
user = User.new(user_params)
end
def user_params
params.permit(:firstname, :lastname, :email, :age, :id)
end
end
end
end
My routes:
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
resources :users
end
end
end
Here is my folder structure:
I got below error in console:
Actually, I have just started in ruby on rails. I tried to figure out problem but couldn't find it.
You need to reference ApplicationController from the Main module (the "global" namespace in Ruby):
module Api
module V1
class UsersController < ::ApplicationController
:: tells Ruby to resolve the constant from main rather than the current module nesting which is Api::V1.
You also need to ensure that ApplicationController inherits from ActionController::API.
See:
Everything you ever wanted to know about constant lookup in Ruby

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