uninitialized constant Api - ruby-on-rails

I am still a beginner concerning ruby on rails and I am trying to create a simple API but I am facing this error :"uninitialized constant Api"
ideas_controller.rb
module Api
module V1
class ItemsController < BaseController
def index
#ideas = Idea.all
render json: #ideas
end
end
end
end
routes.db
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
resources :ideas
end
end
end
application_controller.rb
class ApplicationController < ActionController
protect_from_forgery with: :null_session
end
base_controller.rb
module Api
module V1
class BaseController < ApplicationController
respond_to :json
end
end
The project's directories:
The server's error:
I have also tried this approach and changed the project's structure to :
Also, I have enabled :
config.eager_load = true
After that I got the following error:
`block in load_missing_constant': uninitialized constant Api::V1::BaseController (NameError)

If you're in the development environment, eager loading is turned off by default, which can be fixed by turning on eager load (change to config.eager_load = true in config/development.rb). Eager loading will allow the whole Rails app to be loaded when the server starts (which is slightly slower), but will fix your problem since that file will be loaded.

This error because module Api is not defined before, I guess if you made like this it gonna work. from an answer here
module Api
module V1
class IdeasController < ApplicationController
def index
#ideas = Idea.all
render json: #ideas
end
end
end
end
another solution could be like this:
module Api
module V1
end
end
class Api::V1::IdeasController < ApplicationController
def index
#ideas = Idea.all
render json: #ideas
end
end
hope it helps.

Try this in your ideas controller
module Api
module V1
class IdeasController < Api::V1::BaseController
def index
#ideas = Idea.all
render json: #ideas
end
end
end
end
And define your base controller in the following way
class Api::V1::BaseController < ApplicationController
respond_to :json
end

Related

Rails api controller doesn't inherit method from the parent class

Doing API for my first Rails project.
I have base class ApiController for all the APIs:
module Api
class ApiController < ::ApplicationController
respond_to :json
skip_before_action :verify_authenticity_token
def index
#collection = resource_class.all
render json: #collection.as_json(as_json_collection)
end
private
def resource_class
raise NotImplementedError
end
def as_json_collection
{}
end
end
end
And I have child class UsersController:
module Api
class UsersController < ApiController
private
def resource_class
User
end
def resource_params
params.require(:user).permit(:name, :email)
end
end
end
My routes:
namespace :api do
resources :users
end
Then I'm going to my_app/api/users I have error:
The action 'index' could not be found for Api::UsersController
But then I changing UsersController writing it's own index class, everything works fine and I'm having all my Users in JSON format.
I've alrady tried to comment all private marks in both classes, but that doesn't help.
I don't want to write an API for every entity in my project and I'd like to avoid this problem in future.
I got it to work with this:
module Api
class ApiController < ::ApplicationController
def index
respond_to do |format|
format.json { render json: '"abc"' }
end
end
end
end
module Api
class UsersController < ApiController
end
end
The URL was http://localhost:3000/api/users.json
So for you I suggest:
module Api
class ApiController < ::ApplicationController
def index
respond_to do |format|
format.json do
#collection = resource_class.all
render json: #collection.as_json(as_json_collection)
end
end
end
end
end
module Api
class UsersController < ApiController
def resource_class
User
end
def resource_params
params.require(:user).permit(:name, :email)
end
end
end
Its supposed to be like this:
class Api::ApiController < ApplicationController
and do not forget to remove extra end, end of the file!
#sample
- api(folder)
-- api_controller.rb (Api::ApiController < ApplicationController)
-- users_controller.rb (Api::UsersController < Api::ApiController)
application_controller.rb
You need to read this my friend:
rails routes
When you do this:
namespace :api do
resources :users
end
rails creates CRUD routes automatically which means that my_app/api/users will translate to: .../users#index.
Do this to see your routes created by rails:
rails routes and for specific word (e.g. user): rails routes | grep user
Seeing is believing ;)

Rails pass value/object/orm from parent controller to child

To keep to restfull protocol, I need to do /api/backup_jobs/777/errors.
In rails, the parent controller- I have:
module Api
class BackupJobsController < ApplicationController
respond_to :json
def show
#backup_job = #backup_jobs.find(params[:id])
respond_with data: #backup_job
end
end
end
in the child controller:
module Api
class ErrorsController < BackupJobsController
respond_to :json
def index
respond_with data: #backup_jobs.find(params[:id]).backup_events.errors
end
end
end
But obvisouley this isn't going to work because params[] doesn't exist for /api/backup_jobs/777/errors
How can I pass the #backup_job = #backup_jobs.find(params[:id]) from the parent controller's def show to the child controller and have it accessible in the child's def index?
You cannot do that because when an ErrorsController is created and used, you will not have a BackupsJobsController that ran before it.
This comes down to the nature of HTTP being a request-response protocol.
Instead, you can extract the line of code you wrote into a method that will be inherited by the ErrorsController.
backup_jobs_controller.rb:
module Api
class BackupJobsController < ApplicationController
def show
find_backup_job
respond_with data: #backup_job
end
protected
def find_backup_job
#backup_job = #backup_jobs.find(params[:id])
# or maybe #backup_job = BackupJob.find(params[:id])
end
end
end
errors_controller.rb:
module Api
class ErrorsController < BackupJobsController
respond_to :json
def index
respond_with data: find_backup_job.backup_events.errors
end
protected
def find_backup_job
#backup_job = BackupJob.find(params[:backup_job_id])
end
end
end

uninitialized constant API::V1::UserController

I know there are already a lot of questions about this on stackoverflow, but none of them works in my case.
In my routes.rb
Exer9::Application.routes.draw do
namespace :api, defaults: {format: 'json'} do
namespace :v1 do
resources :users
end
end
end
exer9/app/controllers/api/v1/users_controller.rb
module Api
module v1
class UsersController < ApplicationController
# GET /user
# GET /user.json
def index
#users = User.all
render json: #users
end
def new
end
def update
end
# GET /user/1
# GET /user/1.json
def show
#user = User.find(params[:id])
render json: #user
end
def create
#user = User.new(params[:user])
if #user.save
render json: #user
else
render json: #user.errors
end
end
def delete
end
def destroy
end
end
end
end
Update
This is my ApplicationController file
class ApplicationController < ActionController::API
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
# protect_from_forgery with: :exception
end
The error message that I get is:
superclass mismatch for class UsersController
Extracted source (around line #2):
1
2
3
4
5
6
class Api::V1::UsersController < ApplicationController
# GET /user
# GET /user.json
def index
Rails.root: /home/steven/Desktop/weekly-exercises/exer9
Application Trace | Framework Trace | Full Trace
app/controllers/api/v1/users_controller.rb:2:in `<top (required)>
'
Any help here is really appreciated!
Use shorter syntax, like:
class Api::V1::UsersController < ApplicationController
# your code goes here
end
Also, do you restart rails server after renaming classes and files?
Make sure your folder structure is correct:
users_controller.rb
should be found:
app/controllers/api/v1/users_controller.rb
You can use it like this
In routes.rb
namespace :api, defaults: {format: 'json'} do
scope module: :v1, constraints: ApiConstraints.new(version: 1 , default: true) do
resources :users
end
end
In controller
class Api::V1::UsersController < ApplicationController
# Your code here
end

Naming error in rails - creating API Controllers

I have my directory under app/controllers set up as such: api/v1/sessions_controller.rb I then have a BaseController: api/v1/base_controller.rb
I then set up each class to look as such:
module Api
module V1
class BaseController < ApplicationController
respond_to :json
before_action :default_json
protected
def default_json
request.format = :json if params[:format].nil?
end
def auth_only!
render :json: {}, status: 401 unless current_user
end
end
end
end
And then Sessions:
module Api
module V1
class SessionsController < BaseController
def create
user = User.authenticate(params[:user_name], params[:password])
if sign_in(user)
set_up_cookie(user)
render json: create_session_data, status: 201
else
invalid_user_crendentials
end
end
end
end
end
The tests are set up the same way, for example the sessions test is:
require 'spec_helper'
describe Api::V1::SessionsController do
before(:each) do
#user = FactoryGirl.create(:user)
end
context "Create a session" do
it "should NOT create a session" do
post :create
response.response_code.should == 401
end
end
end
The Error:
'<module:V1>': uninitialized constant Api::V1::BaseController (NameError)
Try formatting your naming slightly differently.
class Api::V1::BaseController < ApplicationController
# code
end
and
class Api::V1::SessionsController < BaseController
# might need to name this Api::V1::BaseController
end

Rails 3.2.8 - How to get methods form application_controller.rb inside of a module?

I have the following method in my controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
private
def check_api_credential(api_key)
if Credential.find_by_key(api_key)
true
else
false
end
end
end
In all the controllers located directly under controllers folder, this method is reachable.
But the controllers files at controllers/api/v1/photos_controller.rb
module Api
module V1
class PhotosController < ActionController::Base
respond_to :json
def create
redirect_to root_url if check_api_credentials(params[:params][2])
if Photo.create(params[:params][0])
render 'success'
else
render 'failure'
end
end
end
end
end
When I try to save I get
undefined method 'check_api_credentials'
How can I access those methods from application_controllers.rb? They are inside of controllers folder.
class ApplicationController < ActionController::Base
class PhotosController < ActionController::Base
Doesn't ring a bell? All other controllers "directly under controllers folder" are inherited from ApplicationController, but PhotosController is not a child of ApplicationController, it is its sibling. That's why it doesn't see the method.
Is there a reason why you didn't inherit PhotosController from ApplicationController?
In your controller or where ever you need to call the private method in different location, you could try a try: method. So in your code,
def create
redirect_to root_url if try: check_api_credentials(params[:params][2])
if Photo.create(params[:params][0])
render 'success'
else
render 'failure'
end
end
It's might solve. Not sure... Just try to add this and run it....

Resources