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
Related
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
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.
If I wish to create rails' routes with only API specific methods, i.e. index, show, create, update and destroy and DO NOT wish to create new and edit.
I can do it in the following way,
resources :aalu, except: [:new, :edit]
Or
resources :tamaatar, only: [:index, :show, :create, :update, :destroy]
Do I have to keep on repeating this except or only on every resource declaration?
Is there any other way to achieve this by specifying it only once?
You can indeed, using with_options. Like this:
with_options except: [:new, :edit] do |opt|
opt.resources :aalu
opt.resources :tamaatar
end
Let me know if that helps!
[edit]
You don't even need to pass the argument to the block in this case. So you can use:
with_options except: [:new, :edit] do
resources :aalu
resources :tamaatar
end
Which I think is a bit neater.
You can specify your included or excluded methods as:
included = {only: [:index, :show, :create, :update, :destroy]}
excluded = {except: [:new, :edit]}
And then while defining the resource, you can use it like
resources :aalu, excluded
OR
resources :aalu, included
I have this url working now on my Rails 4.2 app - https://example.org/causes/help-family What do I need to do to change the url's to look like this - https://example.org/help-family without the "causes" controller showing up in the route?
https://example.org/causes should still continue to list all the causes.
This is what part of my routes file looks like.
resources :causes, only: [:new, :create, :index, :show] do
get :thankyou
resources :donations, only: [:new, :create, :show ]
end
Thank you!
You can do:
resources :causes, path: '/', only: [:new, :create, :show] do
get :thankyou
get :index, path: 'causes', on: :collection
resources :donations, only: [:new, :create, :show ]
end
This is assuming you only want to keep the 'causes' in the path for the index page.
you can try it
get '/help-family', to: "causes#help-family"
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.