I want member routes generating by resources to contain additional parameter.
Something like:
resources :users
with folowing routes:
users/:id/:another_param
users/:id/:another_param/edit
Any ideas ?
resources method doesn't allow you to do that. But you can do something similar using the path option and including extra parameters:
resources :users, path: "users/:another_param"
That will generate urls like this:
users/:another_param/:id
users/:another_param/:id/edit
In this case you will need to send :another_param value to routing helpers manually:
edit_user_path(#user, another_param: "another_value")
# => "/users/another_value/#{#user.id}/edit"
Passing :another_param value is not required if a default value has been set:
resources :users, path: "users/:another_param", defaults: {another_param: "default_value"}
edit_user_path(#user) # => "/users/default_value/#{#user.id}/edit"
Or you can even make the extra parameter not mandatory in the path:
resources :users, path: "users/(:another_param)"
edit_user_path(#user) # => "/users/#{#user.id}/edit"
edit_user_path(#user, another_param: "another_value")
# => "/users/another_value/#{#user.id}/edit"
# The same can be achieved by setting default value as empty string:
resources :users, path: "users/:another_param", defaults: {another_param: ""}
If you need extra parameters for particular actions, it can be done this way:
resources :users, only: [:index, :new, :create]
# adding extra parameter for member actions only
resources :users, path: "users/:another_param/", only: [:show, :edit, :update, :destroy]
you could do something more explicit like
get 'my_controller/my_action/:params_01/:params_02', :controller => 'my_controller', :action => 'my_action'
resources :users, path: 'user' do
collection do
get ':id/:some_param', action: :action_name
get ':id/:some_param/edit', action: :custom_edit
end
end
Related
I am trying to make some alias for my rails route like this 'events/8/event_participants/new' to /business-meet/registration,
My routes are written like this:
resources :events, only: [], shallow: true do
resources :event_participants, only: [:new, :create, :edit, :update] do
post :complete, on: :collection
member do
get :invite, :add_people, :accept_invitation, :invitation_success, :reserved
put :refer
end
end
end
I want the alias for the specific event id 8, I tried with redirect, but it actually redirect to the the route, so the whole route is visible in the browser, I want the to keep visible /business-meet/registration routes to my browser.
You can use a match method in your route.
match '/business-meet/registration', to: 'event_participants#new', via: :get, defaults: { event_id: 8 }
I'm deploying my Rails app that uses the clearance gem to Heroku. Everything works fine in development but I'm running into trouble with the gem generated routes I get.
When attempting to deploy to Heroku, I get the error...
ArgumentError: Invalid route name, already in use: 'sign_in'
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. For the latter, you can restrict the routes created with `resources` as explained here:
remote: http://guides.rubyonrails.org/routing.html#restricting-the-routes-created
I'm not seeing where to restrict the duplicates or where they would be generated with any of my resources:
Please see routes.rb file below
Routes.rb
Rails.application.routes.draw do
resources :passwords, controller: "clearance/passwords", only: [:create, :new]
resource :session, controller: "clearance/sessions", only: [:create]
resources :users, controller: "clearance/users", only: [:create] do
resource :password,
controller: "clearance/passwords",
only: [:create, :edit, :update]
end
get "/sign_in" => "clearance/sessions#new", as: "sign_in"
delete "/sign_out" => "clearance/sessions#destroy", as: "sign_out"
get "/sign_up" => "clearance/users#new", as: "sign_up"
get 'newSignUp', to: 'signups#new'
post 'newSignUp', to: 'signups#create'
get 'newTrip', to: 'trips#new'
post 'newTrip', to: 'trips#create'
get 'trips/:id/send_itinerary' => 'trips#send_itinerary', as: :trips_send_itinerary
root 'static_pages#home'
get 'static_pages/home'
get 'static_pages/help'
get 'static_pages/about'
get 'static_pages/contact'
resources :signups
resources :tripitems
resources :trips
end
This issue has to do with the clearance gem.
I am not totally familiar with the gem, so as per usual, I checked out the github and found the following:
# config/routes.rb
if Clearance.configuration.routes_enabled?
Rails.application.routes.draw do
resources :passwords,
controller: 'clearance/passwords',
only: [:create, :new]
resource :session,
controller: 'clearance/sessions',
only: [:create]
resources :users,
controller: 'clearance/users',
only: Clearance.configuration.user_actions do
resource :password,
controller: 'clearance/passwords',
only: [:create, :edit, :update]
end
get '/sign_in' => 'clearance/sessions#new', as: 'sign_in'
delete '/sign_out' => 'clearance/sessions#destroy', as: 'sign_out'
if Clearance.configuration.allow_sign_up?
get '/sign_up' => 'clearance/users#new', as: 'sign_up'
end
end
end
This is basically creating the same routes for you, only if the config routes_enabled? is true.
You need to configure clearance as follows to handle the routes yourself:
config.routes = false
After looking at the gems GitHub, it looks like I raked the routes earlier and even though config.routes was set to false in the initializer, there was a conflict generate in the generated resources in production.
I wound up deleting the raked routes and making config.routes=true.
I my routes file, I have defined a resource
namespace :admin do
resources :invoices, only: [:index, :new]
end
Then I've got a route rule with corresponding path helper new_admin_invoice_path
new_admin_invoice GET /admin/invoices/new(.:format) admin/invoices#new
But how can I add two more new rules, so thуe look like
new_admin_incoming_invoice GET /admin/invoices/new/incoming(.:format) admin/invoices#new {:type=>:incoming}
new_admin_outgoing_invoice GET /admin/invoices/new/outgoing(.:format) admin/invoices#new {:type=>:outgoing}
I tried add them manually
resources :invoices, only: [:index, :new] do
get 'new/incoming', on: :collection, action: :new, type: :incoming
get 'new/outgoing', on: :collection, action: :new, type: :outgoing
end
But got wrong result
new_incoming_admin_invoices GET /admin/invoices/new/incoming(.:format) admin/invoices#new {:type=>:incoming}
new_outgoing_admin_invoices GET /admin/invoices/new/outgoing(.:format) admin/invoices#new {:type=>:outgoing}
How can I get exactly that routes with path helpers what I need?
Here is the easy rails way from official guide
resources :invoices, only: [:index] do
get 'incoming', on: :new, type: :incoming, action: :new
end
Results to
incoming_new_admin_invoice GET /admin/invoices/new/incoming(.:format) admin/invoices#new {:type=>:incoming}
Try by using a scope like this:
scope "/admin" do resources :invoices end
How to rename index path only?
routes.rb
resources :tasks, :except => [:create] do
collection do
..............
end
member do
.............
end
end
instead of /tasks in URL I need /trigger or even /tasks/trigger will do, im on rails3.
I tried
1.
collection do
'/', to: 'tasks#trigger'
end
and
2.
resources :tasks, :except => [:create] do
get '/task', to: 'task#trigger', as: task_index
end
both throw up errors.
any ideas?
For URL like '/trigger' add to routes.rb:
get 'trigger' => 'tasks#index'
For URL like '/tasks/trigger' modify routes.rb:
resources :tasks, :except => [:create] do
collection do
get 'trigger' => 'tasks#index'
end
end
If your index method in task's controller named as 'trigger, 'tasks#index' is replaced by 'tasks#trigger'
If you want to make your own index route then you need to do two things
1- you need to disable index path created by resources
2- Define your own path whatever you want.
As per your requirement you want to make index route as '/trigger'.
Following is the solution.
get 'trigger' => 'tasks#index'
resources :tasks, :except => [:create, :index] do
collection do
..............
end
member do
.............
end
end
Just restraint index route from being generated in your resources call:
resources :tasks, :except => [:create, :index]
And then do your own custom route. For '/trigger':
get 'trigger', to: 'task#trigger', as: 'trigger
I'm developing a REST API based on rails. To use this API, you MUST be logged in. Regarding that, I'd like to create a method me in my user controller that will return a JSON of the logged in user infos.
So, I don't need an :id to be passed in the URL. I just want to call http://example.com/api/users/me
So I tried this:
namespace :api, defaults: { format: 'json' } do
scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
resources :tokens, :only => [:create, :destroy]
resources :users, :only => [:index, :update] do
# I tried this
match 'me', :via => :get
# => api_user_me GET /api/users/:user_id/me(.:format) api/v1/users#me {:format=>"json"}
# Then I tried this
member do
get 'me'
end
# => me_api_user GET /api/users/:id/me(.:format) api/v1/users#me {:format=>"json"}
end
end
end
As you can see, my route waits for an id, but I'd like to get something like devise has. Something based on current_user id. Example below:
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
In this example you can edit the current user password without passing the id as a param.
I could use a collection instead of a member, but that's a dirty bypass.
The way to go is to use singular resources:
So, instead of resources use resource:
Sometimes, you have a resource that clients always look up without referencing an ID. For example, you would like /profile to always show the profile of the currently logged in user. In this case, you can use a singular resource to map /profile (rather than /profile/:id) to the show action [...]
So, in your case:
resource :user do
get :me, on: :member
end
# => me_api_user GET /api/users/me(.:format) api/v1/users#me {:format=>"json"}
Resource routes are designed to work this way. If you want something different, design it yourself, like this.
match 'users/me' => 'users#me', :via => :get
Put it outside of your resources :users block
You can use
resources :users, only: [:index, :update] do
get :me, on: :collection
end
or
resources :users, only: [:index, :update] do
collection do
get :me
end
end
"A member route will require an ID, because it acts on a member. A collection route doesn't because it acts on a collection of objects. Preview is an example of a member route, because it acts on (and displays) a single object. Search is an example of a collection route, because it acts on (and displays) a collection of objects." (from here)
Maybe I am missing something, but why don't you use:
get 'me', on: :collection
resources :users, only: [:index, :update] do
collection do
get :me, action: 'show'
end
end
specifying the action is optional. you can skip action here and name your controller action as me.
This gives same result as Arjan's in simpler way
get 'users/me', to: 'users#me'
When you create a route nested within a resource, you can mention, whether it is member action or a collection action.
namespace :api, defaults: { format: 'json' } do
scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
resources :tokens, :only => [:create, :destroy]
resources :users, :only => [:index, :update] do
# I tried this
match 'me', :via => :get, :collection => true
...
...