Unitialized Constant Rails Routing - ruby-on-rails

I have a rails 4 app where I have a controller like:
app/controllers/api/v1/books_controller.rb:
module Api::V1
class BooksController < ApplicationController
...
end
end
and then my routes.rb:
namespace :api, defaults: {format: 'json'} do
namespace :v1 do
resources :books
end
end
But I'm getting the error:
uninitialized constant BooksController

Try this:
module Api
module V1
class BooksController < ApplicationController
...
end
end
end
or this:
class Api::V1::BooksController < ApplicationController
...
end
Both works for me.
Also there is a good practice to have some API Controller in like:
module Api
class BaseController < ApplicationController
respond_to :json
end
end
in api folder. Or it can be in api version folder, with version namespace.

Related

In namespaced api (Api::V1) I can't access serializers

Api::V1 is the namespacing of my schedules#index resource. But the controller won't access the serializer.
module Api
module V1
class ApiController < ApplicationController
include ActionController::Serialization
include Concerns::ErrorHandler
before_action do
namespace_for_serializer = Api::V1
end
end
end
end
module Api
module V1
class SchedulesController < ApiController
def index
#schedules = current_user.schedules
render json: #schedules
end
end
end
end
module Api
module V1
class ScheduleSerializer < ActiveModel::Serializer
attributes :id
end
end
end
I've tried everything. Declare the serializer directly vs each_serializer: ScheduleSerializer which just returns an "uninitialized constant" error.
What am I missing?

Defining a custom route in a namespaced api in rails application

I have created a namespaced api in my rails 5 project. I have the following in my config/routes.rb
Rails.application.routes.draw do
post 'api_user_token' => 'api_user_token#create'
namespace :api do
namespace :v1 do
resources :events
end
end
end
Events Controller
module Api::V1
class EventsController < ApiController
#Code here
end
end
API Controller
module Api::V1
class ApiController < ApplicationController
before_action :authenticate_api_user
respond_to :json
def register
end
end
end
I want the '/api/v1/register' route to go to the register method defined in my api controller. How can i define the route in this case ?
Thanks
namespace :api do
namespace :v1 do
resources :events
post :register, to: 'apis#register'
end
end
This will generate
api_v1_register POST /api/v1/register(.:format) api/v1/apis#register

Rails and Devise: Error with namespace

What I need is that when a user goes to '/admin', it redirects to '/admins/sign_in' for the user to sign in.
This is what I did:
# routes.rb
devise_for :admins
namespace :admin do
root to: 'users#index'
end
.
# controllers/admin/base_controller.rb
class Admin::BaseController < ApplicationController
before_action :authenticate_user!
layout 'admin'
end
.
# controllers/admin/users_controller.rb
class Admin::UsersController < Admin::BaseController
def index
end
end
The problem is that when I go to '/admin' it returns me an error:
NoMethodError in Admin::UsersController#index ..
undefined method `authenticate_user!' for Admin::UsersController
How can I make it work?
We have nearly the same setup as you, and it works perfectly:
I think the problem is that you're using devise_for :admins, and yet calling authenticate_user!; it should be authenticate_admin! (as per the Devise docs):
class Admin::BaseController < ApplicationController
before_action :authenticate_admin!
end

Nesting resources within a singular resource

Given the following routes:
resource :public_profile do
resources :posts
end
resource :private_profile do
resources :posts
end
How can I, in the PostsController, determine which singular resource I am nested within?
One way you could do this is by creating 2 more controllers that extend some main PostsController, and use
resource :public_profile do
resources :posts, controller: "PublicPostsController"
end
resource :private_profile do
resources :posts, controller: "PrivatePostsController"
end
You could even do this in a variety of ways. For example, maybe it makes sense to have
class ProfileController < ApplicationController; end
class PostsController < ApplicationController; end
class Private::ProfileController < ProfileController; end
class Private::PostsController < PostsController; end
class Public::ProfileController < ProfileController; end
class Public::PostsController < PostsController; end
with routing
resource :public_profile, controller: "Public::ProfileController" do
resources :posts, controller: "Public::PostsController"
end
resource :private_profile, controller: "Private::ProfileController" do
resources :posts, controller: "Private::PostsController"
end
Regardless of how you set this up, you can easily 'know' what resource you're nested within because you'll actually be running within a separate controller specific to that nesting and can thus have a perfect place for logic specific to that nesting. For general logic, you'd put that into the parent PostsController.
Another way you could do this is by adding a before_filter to PostsController like
before_filter :check_nesting
private
def check_nesting
#is_public_profile = params.include?(:public)
end
and have routing like
resource :public_profile, public: true do
resources :posts, controller: "PublicPostsController"
end
resource :private_profile, private: true do
resources :posts, controller: "PrivatePostsController"
end
I don't care for this approach though.
You can route them to different controllers ( by specifying it in the routes) , that are extended from the same "base" controller PostsController. In the extended controllers you
identify them:
EX:
resource :public_profile do
resources :posts, :controller => "public_profile_posts_controller"
end
resource :private_profile do
resources :posts, :controller => "private_profile_posts_controller"
end
and the Controllers
class PublicProfilePostsController < PostsController
before_filter :identify_controller
def identify_controller
#nested_resource_of = :public_profile
end
end
class PrivateProfilePostsController < PostsController
before_filter :identify_controller
def identify_controller
#nested_resource_of = :private_profile
end
end
and then you have access to the variable
#nested_resource_of
in the PostsController actions

set layout in routes into the scope

I have admin controller and I want to set layout for '/admin' path.
I try like:
scope '/admin' do
layout 'admin' # did't work
get '/' => 'admin#index', as: 'admin'
resources :posts, as: 'admin_posts'
end
I can set layout in AdminController like:
class AdminController < ApplicationController
layout 'admin'
end
but is a bad way because rationally use some layout for all controllers who call from '/admin' path
How I can do it?
You cant set layout directly in your routes.rb
I think what you do is the right way
class AdminController < ApplicationController
layout 'admin'
end
Now you will use AdminController to generate other controllers in admin scope
class UsersController < AdminController
end
or if in a namespace
class Admin::UsersController < AdminController
end
Thats what i do, if i did understand your question.

Resources