routes in rails - removing actions when setting up a resource - ruby-on-rails

I've setup a simple app and added a scaffold to do some of the work for me (I'm a noob).
resources :cars
How do I remove certain actions from the routes? And remove the corresponding urls?
For example I want to keep the 'show' and 'edit' actions & urls.
But I don't want there to be a 'new' 'index' or 'delete'
I understand this is probably a really simple question, but I've not been able to find an answer.

resources :cars, :except => [:new, :index, :delete]
or
resources :cars, :only => [:show, :edit]
Also take a look at Rails Guides

If you want to remove some actions then you can mention action name in the array
resources :photos, only: [:index, :show]
But
if you want to disable all the default CRUD actions then you should use
resources :photos, only: []

Related

rails - how to target nested controller for nested resource route

In my routes.rb I have
namespace :admin do
resources :clients do, only: [:index] do
resources :products, only: [:index, :new, :create]
end
resources :products, only: [:index]
end
Notice that I have two lines for resources :products. One is nested within resources :clients and the other as a top-level resource on :admin; each of these two has a different purpose in the application.
rake routes gives me:
admin_clients GET /admin/clients(.:format) admin/clients#index
admin_client_products GET /admin/clients/:client_id/products(.:format) admin/products#index
POST /admin/clients/:client_id/products(.:format) admin/products#create
new_admin_client_product GET /admin/clients/:client_id/products/new(.:format) admin/products#new
admin_products GET /admin/products(.:format) admin/products#index
I have a admin_client_products for the nested product#index resource. I also have admin_products for the top-level product#index resource. However, they point to the same controller action: admin/product#index.
Question: At this point, I need rails to deduce that these are two different actions. Using rails conventions, is there a way to tell rails that these two resources should have different controller actions i.e. one that should hit admin/products#index and the other should hit admin/clients/products#index?
The nested route should hit this:
class Admin::Clients::ProductsController < Admin::BaseController
def index; end
end
The top-level route should hit this:
class Admin::ProductsController < Admin::BaseController
def index; end
end
Definitely you can!
Here you need to customize your resourceful route by explicitly specifying a controller to use for the resource. The :controller option will let you do that.
So, in your case, specifying the controller as clients/products for the admin_clients_products resource would work in your desired way.
namespace :admin do
resources :clients, only: [:index] do
resources :products, only: [:index, :new, :create], controller: 'clients/products'
end # ------------------------------
resources :products, only: [:index]
end
rails routes will now give you what you want:
admin_client_products GET /admin/clients/:client_id/products(.:format) admin/clients/products#index
POST /admin/clients/:client_id/products(.:format) admin/clients/products#create
new_admin_client_product GET /admin/clients/:client_id/products/new(.:format) admin/clients/products#new
admin_clients GET /admin/clients(.:format) admin/clients#index
admin_products GET /admin/products(.:format) admin/products#index
=========================
Extra bits:
If you want to omit the /admin portion from the url (I mean, if your application's routing design permits to), then you could use: scope module: 'admin' do...end like the following:
scope module: 'admin' do
resources :clients, only: [:index] do
resources :products, only: [:index, :new, :create], controller: 'clients/products'
end
resources :products, only: [:index]
end
and suddenly your routes will start looking awesome :)
client_products GET /clients/:client_id/products(.:format) admin/clients/products#index
POST /clients/:client_id/products(.:format) admin/clients/products#create
new_client_product GET /clients/:client_id/products/new(.:format) admin/clients/products#new
clients GET /clients(.:format) admin/clients#index
products GET /products(.:format) admin/products#index

How to create a custom route inside resource without overwrite path

I’ve this on routes.rb
resources :questions, except: [:show] do
get '/resource/:subject/:id', to: 'resource#show', as: "resource", param: [:name, :id]
It says that:
Invalid route name, already in use: ‘resource' You may have defined two routes with the same name using the :as option, or you may be overriding a route already defined by a resource with the same naming
I know that resources create two routes with the same path, show and destroy both uses resource_path, how does it is being created internally? and how i can generate my route for show wihtout overwrite the one in destroy?
A good way to eliminate routes unneeded is by specifying the :only option
resources :user, :only => [:edit]
instead of
resources :user, :except => [:new, :create, :edit, :update, :show, :destroy]
It seems to me that you could take out show and then define the route that you want separately. See if this works:
resources :questions, except: :show
get '/resource/:subject/:id',
to: 'resource#show',
as: "resource", # This is where the error is.
param: [:name, :id]
EDIT: Ah, yes. The :as parameter needs a different name. This will work:
resources :questions, except: :show
get '/resource/:subject/:id',
to: 'resource#show',
as: "resource_show",
param: [:name, :id]

Nested resource and restricting the Routes Created :only and :except

Good day all,
Can someone kindly assist me with nested resources and its best practice.
I would like to restrict my :events route to only :show and :index, is this the correct way of doing it?
resources :events do
resources :registrations, :except => [:index]
end
resources :events, :only => [:index, :show]
Is this the best way or the way more Rubyist would handle such thing? I've added two lines of resources :events or is there a way to combine it all in 1 block?
Thanks in advance.
Yes. You can combine it in one block like:
resources :events, only: [:index, :show] do
resources :registrations, except: :index
end

How do I make my UsersController work nicely with current_user?

Users can view and edit account information in my app using UsersController
This controller only ever shows information about the current user.
I want to adjust the routes so that:
get /account accesses UsersController#show, user_id is retrieved from a current_user variable
get /account/edit similarly accesses UsersController#edit
put /account/ will hit UsersController#update, again using current_user instead of an ID
Basically I want to refer to UsersController as 'account' in my URLs and I don't want to use IDs because I'm always just using the current user. I also don't want URLs like /users/1 to function at all.
How can I achieve this?
I think that you are talking about singular resources.
http://guides.rubyonrails.org/routing.html#singular-resources
# Not sure if you need this
resource :users, :only => [:index, :create, :destroy]
# This is what you are looking for
resource :user, :as => :account, :only => [:show, :edit, :update]
Update
Since you need "/account" instead of "/user", you should do
resource :account, :controller => :users, :only => [:show, :edit, :update]
Given your setup, you probably have something like this in your routes.rb:
resources :users
You should be able to just change it to this:
resources :users, :as => "account"
I haven't tested it but this should work. For more info, check the Rails guides on Routing.
Two ways to do it:
In your route.rb:
resources :users, :as=>'accounts'
In your route.rb, remove resources :users and add:
match '/account'=>'users#show'
match '/account/edit'=>'users#edit'
match '/account/'=>'users#update'

Renaming path helpers in Rails 3 routing

I have a projects controller/model. Instead of listing projects on the #index page, I show a list of drop downs, which submits to projects#select, which finds the right Project (I've made sure there can only be 1 for each combination of options) and forwards the user to the #show page for that Project.
So for my routes I do this...
resources :projects, :only => [:index, :show] do
collection do
get 'select'
end
end
And thats fine, but the helper method for #select is 'select_projects', which is understandable but in my case I really want 'select_project'. And I really don't want to alias this in another file. No problem I can use :as...
resources :projects, :only => [:index, :show] do
collection do
get 'select', :as => 'select_project'
end
end
But now my helper is 'select_project_projects'. So I cheat a little (still better than aliasing in another file)...
resources :projects, :only => [:index, :show]
match '/projects/select', :to => 'projects#select', :as => 'select_project'
This looks like it might work, but it doesn't because /project/select actually matches the route for 'project#show'. Changing the order of the lines does the trick.
match '/projects/select', :to => 'projects#select', :as => 'select_project'
resources :projects, :only => [:index, :show]
But is there a more elegant way of handling this? I realize this is borderline OCD, but I'd like to be able to have complete control over the route name within the resources block.
use resource instead of resources
you probably don't want to make it a collection route but a member route:
resources :projects, :only => [:index, :show] do
member do
get 'select'
end
end
This way you'll have the select_project helper.
For those that want to rename the helper method side of things (as the title suggests):
resources :posts, as: "articles"

Resources