Routing Error : uninitialized constant when split controller routes into namespaced route - ruby-on-rails

I have routes like this below. Is it possible if I have routes like this ?
#config/routes
resources :subscribers, only: [:index, :show]
namespace :admin do
resources :subscribers, only: [:new, :edit, :update, :create, :destroy]
end
I have tried to run rake routes and the result is
admin_subscribers POST /admin/subscribers(.:format) admin/subscribers#create
new_admin_subscriber GET /admin/subscribers/new(.:format) admin/subscribers#new
edit_admin_subscriber GET /admin/subscribers/:id/edit(.:format) admin/subscribers#edit
admin_subscriber PUT /admin/subscribers/:id(.:format) admin/subscribers#update
DELETE /admin/subscribers/:id(.:format) admin/subscribers#destroy
subscribers GET /subscribers(.:format) subscribers#index
subscriber GET /subscribers/:id(.:format) subscribers#show
the result was appropriate with my expectation, but when i run my RSpec i got errors
Routing Error
uninitialized constant Admin::SubscribersController
Try running rake routes for more information on available routes.
I added this code below in my Rspec Helper too
#spec/spec_helper.rb
Spork.each_run do
###
if /spork/i =~ $0 || RSpec.configuration.drb?
ActiveSupport::Dependencies.clear
end
###
end
But, if I fire my browser to htt**://l*alhost:3000/admin/subscribers/new, everything is fine.
Am I missing something ?

As stated in the docs
If you want to route /admin/subscribers to SubscribersController (without the Admin:: module prefix), you could use scope instead of namespace
#config/routes
resources :subscribers, only: [:index, :show]
scope "/admin" do
resources :subscribers, only: [:new, :edit, :update, :create, :destroy]
end

I don't think there's much need for you to namespace this under admin. You could just fill in all the actions on SubscribersController and set the permissions on create, update etc. appropriately.

Related

Rails 6 routes - proper way of simple nesting routes

Because it's been a while since I was using Rails monolith instead of GrapeAPI I've silly question. I want to create a route for path - users/portfolios/1/portfolio_reports/archived_reports where I will displays PortfolioReports.where(status: 'archived'). I created routes:
namespace :users do
resources :portfolios, only: [:index, :show] do
resources :archived_report, only: [:index, :show]
resources :portfolio_report, only: [:index, :show]
end
end
So I've got two questions: Should the routes file look like my current routes.rb ? and if I have Portfolio and PortfolioReport models like below, the portfolio_reports_controller should be inside app/controllers/users/portfolio_reports_controller.rb or app/controllers/portfolio_reports_controller.rb ?
class Portfolio
has_many :portfolio_reports
end
class PortfolioReport
belongs_to :portfolio
end
In Rails you can use "Shallow Nesting" which basically says to only nest the index, new and create actions under the parent resource. For the other actions you don't need to nest the routes, because through the record itself you have access to the associated record, so there is no need to have the id in the url.
So your routes will be:
users/portfolios/ # Portfolios#index
users/portfolios/1 # Portfolios#show
users/portfolios/1/portfolio_reports # PortfolioReports#index
users/portfolio_reports/1 # PortfolioReports#show
users/portfolios/1/archived_reports # ArchivedReports#index
users/archived_reports/1 # ArchivedReports#show
And routes.rb should look like this:
namespace :users do
resources :portfolios, only: [:index, :show] do
resources :archived_report, only: [:index]
resources :portfolio_report, only: [:index]
end
resources :archived_report, only: [:show]
resources :portfolio_report, only: [:show]
end
(If you'd use all 7 routes you could use the helper shallow as mentioned in the docs).
No need to nest archived_reports under portfolio_reports like you mentioned in your question!
Find more info on shallow nesting here: https://guides.rubyonrails.org/routing.html#shallow-nesting
For the user namespace:
Your controllers should live in a subfolder user because you have the namespace user:
app/controllers/user/portfolio_reports_controller.rb

Routing Error uninitialized constant Meetups

I am currently stuck getting a Routing Error for uninitialized constant Meetups
class MeetupsController < ApplicationController
before_action :set_meetup, only: [:edit, :update, :destroy]
def create
#meetup = Meetup.new(host: current_user)
#meetup.save
redirect_to meetup_create_path(Wicked::FIRST_STEP, meetup_id: #meetup.id)
end
end
This is my create function inside my MeetupsController, as you can see the controller name is plural and the file name is 'meetups_controller.rb'
Below is my routes.rb
Rails.application.routes.draw do
devise_for :users
resources :users
resources :meetups, except: [:show] do
resources :create, controller: 'meetups/setup'
resources :participations, only: [:new]
member do
get "create/review", to: 'meetups/setup#review'
end
end
root to: 'pages#home'
get 'join_meetup', to: 'pages#join_meetup'
get 'events', to: 'pages#events'
get 'landing', to: 'pages#landing'
end
Any help would be greatly appreciated.
Error trace would be more helpful.
But looking at resources :create, controller: 'meetups/setup' in routes file, I could guess that the Rails application is Expecting namespaced controller as Meetups::SetupController.
So you need to change your controller accordingly. You need to create a namespaced controller or may be a scoped controller.
Reference: http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing

No matching Route error in Ruby on Rails

I am new in Ruby on Rails. I have been trying for two days to define a route for a method in the controller but error shows saying "No route matches [GET]".
Here is the code
donations Controller:
before_action :set_donation, only: [:show, :edit, :update, :destroy, :create_user_account]
before_action :set_campaign, only: [:new, :create_user_account]
//this is the method that i want to call
def create_user_account
end
Here is my route file
Rails.application.routes.draw do
resources :donations, except: [:new, :create]
get 'donations/create_user_account' => 'donations#create_user_account'
resources :campaigns do
resources :donations, only: [:new, :create, :create_user_account]
get 'donations/create_user_account' => 'donations#create_user_account'
end
resources :organizations
devise_for :users
root to: "campaigns#latest"
end
The routes are showing my route name but when i hit the route "no matching" route error occurs.
route1:
campaign_donations_create_user_account_path GET /campaigns/:campaign_id/donations/create_user_account(.:format)
donations#create_user_account
route2:
donations_create_user_account_path GET /donations/create_user_account(.:format)
donations#create_user_account
I want to call route 2 but no route is working
I call my route 2 like this
http://localhost:3000/donations/create_uer_account
This is the error
The error is because this line
resources :donations, except: [:new, :create]
is before the others in routes.rb. Rails matches with the first route it finds in the routes.rb file.
It should look something like this
get 'donations/create_user_account' => 'donations#create_user_account'
resources :donations, except: [:new, :create]
then Rails matches with your create_user_account first.

Rails routes: GET method redirecting to show method

I have simple controller and routes file.
In my route and controller i have created a module. I wrote a simple method which is redirecting me show. I am not sure why.
Controller
module Seller
class CampaignsController < Seller::BaseController
before_action :confirm_logged_in
def viewAllCampaigns
#campaigns = Campaign.all
end
def show
end
end
end
Routes file
scope module: 'seller' do
#namespace :power do
resources :dashboard, only: [:index]
resources :sessions, only: [:create, :destroy]
resources :campaigns, only: [:index, :create, :show, :update, :destroy]
get 'viewAllCampaigns' => 'campaigns#viewAllCampaigns'
end
Output
Started GET "/campaigns/viewAllCampaigns" for 127.0.0.1 at 2015-10-12 17:39:43 +0500
Processing by Seller::CampaignsController#show as HTML
Parameters: {"id"=>"viewAllCampaigns"}
Rendered seller/campaigns/show.html.erb (0.1ms)
I am hitting http://localhost:3000/campaigns/viewAllCampaigns in browser.
Ideally your routes should be defined like this.
resources :campaigns, only: [:index, :create, :show, :update, :destroy] do
get 'viewAllCampaigns', on: :collection
end
The first comment on the routes.rb file is The priority is based upon order of creation: first created -> highest priority. This is the reason your route is redirecting to show. Rails is treating this url as campain/:id.
Routes are tested in order, from top to bottom. The show route you've added for the campaigns resource will look for urls matching this pattern:
/campaigns/:id
/campaigns/viewAllCampaigns matches this, so it will do the show action., with params[:id] = "viewAllCampaigns"
Move the special case route up above the resources#campaigns route to fix this, then it will catch the url first.
get 'viewAllCampaigns' => 'campaigns#viewAllCampaigns'
resources :campaigns, only: [:index, :create, :show, :update, :destroy]
It takes the following get request as a show action because show expects campaigns/:id, and it assumes 'viewAllCampaigns' is an id in this instance:
/campaigns/viewAllCampaigns
Your link_to should just be pointing to the following:
'/viewAllCampaigns'
Your route structure isn't really RESTful, but that's a separate topic.

How to create routes path into resource in rails 3

I understand resource and path routes in rails 3 but I do not know is there any way to have both routes ? I try this routes but it not work for me, this is the routes:
resources :roles, only: [:index, :create, :show, :update]
get '/roles/:id' => 'roles#available_users'
How can we routes to use both routes ?
thankyou very much
Routes
What you're asking for cannot be done, as you'll be using the same "route" for different controller actions:
#config/routes.rb
resources :roles, only: [:index, :create, :show, :update] #-> domain.com/roles/:id - roles#show
If you then create another route for domain.com/roles/:id, Rails will just take the first which it finds in the routes file
--
The way to fix your issue is likely to be down to the following:
#config/routes.rb
resources :roles, except: [:edit, :destroy] do
get :available_users # -> domain.com/roles/:id/available_users
end
This will take you to the roles#available_users action, providing you with the ability to load the view you wish (to display the users for a particular role)
For a more defined explanation, I'd recommend checking out the nested_resources part of the Rails routing system
If I understand you correctly you want something like this:
resources :roles, only: [:index, :create, :update] do
get '/roles/:id' => 'roles#available_users'
end
Correct?
Just add an "do" behind the closing ] and an end after the custom routes.
Edit: Apparently I got wrong. ;) What you could do is:
resources :roles, only: [:index, :create, :show, :update] do
get '/roles/:id/available' => 'roles#available_users'
end

Resources