I want to configure my Rails routing such that these cases work:
/username #=> { :controller => "houses",
# :action => "index",
# :user_id => "username" }
/username/housename #=> { :controller => "houses",
# :action => "show",
# :user_id => "username",
# :id => "housename" }
/username/edit #=> { :controller => "users",
# :action => "edit",
# :id => "username" }
In other words, I want /:user_id to be a regular user resource, and have a nested resource for it, which is mounted directly on the root. So, I want /username/housename instead of /username/houses/housename. I tried using :path => "/" for the nested resources, but this somehow clashes with other actions such as `:edit. I'm lost - can this be done?
What you are trying to do will create conflicts, which is why Rails is not letting you do it.
Consider the situation where some user bob has a house named "edit". In this case, where is Rails supposed to route '/bob/edit' to? There are two possibilities:
{ :controller => "houses", :action => "show", :user_id => "bob", :id => "edit" }
and:
{ :controller => "users", :action => "edit", :id => "bob" }
So to answer your question, as is what you are trying to do cannot be done until you remove the ambiguity.
UPDATE:
Borrowing from #sevenseacat's answer, I think this should do what you want, in the case of a route /bob/edit prioritizing the edit action for user "bob" over the show action for a house named "edit":
resources :users, path: '/', only: :edit
resources :users, path: '/', only: :show do
resources :houses, only: :show, path: ''
end
I get these routes:
edit_user GET /:id/edit(.:format) users#edit
user_house GET /:user_id/:id(.:format) houses#show
user GET /:id(.:format) users#show
Notice that the edit_user path appears above the user_house path, which guarantees that it will get priority when there is a conflict.
Something like this may be what you're after:
resources :users, path: '/', only: [:show, :edit] do
resources :houses, only: [:show], path: ''
end
rake routes tells me:
user_house GET /:user_id/:id(.:format) houses#show
edit_user GET /:id/edit(.:format) users#edit
GET /:id(.:format) users#show
Related
I am trying to call an action from a controller 2 steps up the folder structure namespace
<%= link_to( "Reset Search" ,
{:controller => "../../application",
:action => 'reset_search',
:reset_search_redirect => reset_search_redirect},
class: 'tiny button') %>
The "../../application"works! however; i dont think it's rails-y. Is there a better way?
Here is the href link when I just put :controller => "application"
/human_resources/settings/application/reset_search?reset_search_redirect=%2Fhuman_resources%2Fsettings
Which does not work.
Here are my routes:
get 'human_resources/' => 'human_resources#index'
namespace :human_resources do
get 'settings/' => 'settings#index'
namespace :settings do
get 'constants/' => 'constants#index'
resources :constants
end
end
resources :test, only: :index
root to: 'home#index'
match ':controller(/:action(/:id))', :via => [:get, :post]
I'm trying to write test for my costume routes, along with non existing routes.
For the examples down here I have two problems:
It matches the actions that don't exist on my controller, so it doesn't really match to see if my controller have those actions, it just matches the syntax
the should_not be_routable doesn't work, which kind of goes back to the above problem of it doesn't check against my controller or the routes.rb file to see if the route should exist.
This one passes and is all good:
it "should route to method1" do
{ :get => '/my_controller/method1' }.should route_to(:controller => 'my_controller',
:action => 'method1')
end
this one fails, so it doesn't even check to see if I have a method zz defined in my controller or routes file.
it "should not route to zz" do
{ :get => '/my_controller/zz' }.should_not be_routable
end
the error I get is:
MyController routing zz should route to rescan
Failure/Error: { :get => '/my_controller/zz' }.should_not be_routable
expected {:get=>"/client_rescan/zz"} not to be routable, but it routes to {:controller=>"my_controller", :action=>"zz"}
So it obviously doesn't look at my routes file at all...
This is another example of it doesn't look at my routes file, in my routes I have ' resources :client_rescan, :only => [:index] ' and when I do rake routes it doesn't show delete as expected, but the test doesn't look at those:
it "should not have route to delete" do
{ :delete => '/my_controller/1'}.should_not be_routable
end
The Failure I get is the following. Which looks like it doesn't even see the delete function:
Failure/Error: { :delete => '/my_controller/1'}.should_not be_routable
expected {:delete=>"/my_controller/1"} not to be routable, but it routes to {:controller=>"my_controller", :action=>"1"}
Another problem is my post routes to index in the test:
it "should not have route to post" do
{ :post => '/my_controller' }.should_not be_routable
end
The Failure I get is:
Failure/Error: { :post => '/my_controller' }.should_not be_routable
expected {:post=>"/my_controller"} not to be routable, but it routes to {:controller=>"my_controller", :action=>"index"}
this is content of my routes.rb file
require 'resque/server'
require 'resque_scheduler'
Cdc::Application.routes.draw do
mount Resque::Server.new, :at => 'resque'
Resque.schedule = YAML.load_file(File.join(File.dirname(__FILE__), 'resque_schedule.yml')) # load the schedule
devise_for :users, :controllers => { :sessions => "sessions", :registrations => "registrations" }
[:assessments, :security_assessments, :privacy_assessments].each do |assessment_type|
resources assessment_type, :controller => :assessments do
resources :rsz do
post 'review', :on => :member
get 'judgement', :on => :member
end
get :judgement, :on => :member
resources :samples do
get 'download', :on => :member
end
resources :asm_reviews do
post :request_review, :on => :collection
end
end
end
resources :account_creator
match "/images/captcha/*file_name" => "captcha#show"
## this is where my route is!! :)
resources :my_controller, :only => [:index] do
collection do
get :rescan
get :cancel
end
end
match "alert_queue/words" => "alert_queue#words"
resources :alert_queue
match "calls_to_action/start/:id" => "calls_to_action#start", :id => /\d+/
match "calls_to_action/close/:id" => "calls_to_action#close", :id => /\d+/
match "calls_to_action/comment/:id" => "calls_to_action#comment", :id => /\d+/
match "calls_to_action/multiclose" => "calls_to_action#multiclose"
match "calls_to_action/multiscan" => "calls_to_action#multiscan"
match "application_instances/multiclose" => "application_instances#multiclose"
match "application_instances/multiscan" => "application_instances#multiscan"
resources :code_categories do
resources :code_families do
resources :code_family_versions
end
end
resources :code_policy_items
resources :application_instances do
collection do
post :resque_statuses
end
resources :code_indices
resources :application_analysis
get "smali/:smali_path", :as => :smali, :on => :member, :action => :smali, :smali_path => /.*/
member do
get :file
get :strings
get :dump
get :alerts
get :correlations
get :signers
get :icon
get :resque_status
get :assets
get :new_code_index
get :class_list
get :heuristic_hits
get :engine_artifacts
post :rescan
post :attach_artifact
post :engine_artifact, :action => :attach_engine_artifact
resources :alerts
end
post "multiscan", :on => :collection, :action => :multiscan
post "multiclose", :on => :collection, :action=> :multiclose
post "engines/:engine_name/:engine_version/assertions/:cookie",
:on => :member, :action => :register_assertion_set, :as => :register_assertion_set,
:engine_name => /[^\/]+/, :engine_version => /[^\/]+/, :cookie => /[^\/]+/
post "engines/:engine_name/:engine_version/network_data",
:on => :member, :action => :register_network_data, :as => :register_network_data,
:engine_name => /[^\/]+/, :engine_version => /[^\/]+/
post "assets", :on => :member, :action => :register_asset_set, :as => :register_asset_set
end
# index gets the list of families, show gets the assertion types for that family
resources :assertion_families
resources :artifacts
resources :dashboard do
collection do
get :last_app_instance
end
end
match '/direct_downloads/' => 'direct_downloads#index'
root :to => "stats#index"
match '/' => 'stats#index'
match 'explorer/query/:format' => 'explorer#query'
match '/:controller(/:action(/:id))'
end
The problem is this line of routes.rb:
match '/:controller(/:action(/:id))'
This is a catch all route, and will match for example /abc/xyz to controller abc, and action xyz.
It's best really not to use catch all routes, in favour of exposing only the functionality you want.
I'm trying to route the following URL:
/shop/{category_id}/{product_id}/
to a controller action called 'product'
I've got this in my routes:
match "/shop/:category/:id" => "shop#product"
and i've got link_to's as follows:
link_to_unless_current "#{t('murals')}", url_for(:controller => 'shop', :category => 'walls', :id => 'murals')
When the urls are output, they are:
http://0.0.0.0:3000/shop?category=walls&id=murals
instead of the desired:
http://0.0.0.0:3000/shop/walls/murals
if i switch the route, so it goes to:
match "/shop/:category/:id" => "shop#index"
this works, but it's not the right action.
Any help would be appreciated.
try this
<%= link_to_unless_current "#{t('murals')}", custom_path(:category => 'walls', :id => 'murals') %>
match "/shop/:category/:id" => "shop#product", :as => :custom
I have implemented devise and set up the routes to prettyify the urls as so (in the routes file):
devise_scope :user do
get "/login" => "devise/sessions#new"
get "/logout" => "devise/sessions#destroy"
get "/register" => "devise/registrations#new"
end
I have global menu in my application.html.erb file, however, which now inserts devise/controller/action on every link that is on the login or register pages, such as
<%= link_to "Upload Video", {:controller => "videos", :action => "new"} %>
becomes devise/videos/new
Any ideas on how to fix this? I can hack around it but I'm pretty sure it is a simple fix.
Cheers,
s
Take out the devise_scope and try something like this:
devise_for :users,
:controllers => {:registrations => 'devise/registrations', :sessions => 'devise/sessions'},
:path => '/',
:path_names => {:sign_in => 'login', :sign_out => 'logout'}
i am trying to delete some rows on my database but when i call destroy action, update action works.
this is delete.html.haml
=form_for #post, :url => {:action => 'destroy', :id => #post.id} do |f|
this is route
resources :post
root :to => "post#index"
match '/delete/:id/', :to => "post#delete"
What's the problem? Anybody does understand?
The :action should be delete, to match the name of the action in your controller:
= form_for #post, :url => {:action => 'delete', :id => #post.id} do |f|
If you are using rails 3 then you need to make sure you have <%= csrf_meta_tag %> in your header. I put mine after my <%= javascript_include_tag... %> tags. Also make sure that you include the rails.js. (This will be on your layout files).
More details here: http://railsforum.com/viewtopic.php?id=38460 Look toward the bottom.
The root entry in your routes should be placed after the matchblock. Plus: seems like you mixed up the controller action and the http verb: use delete in the form action and destroy in the controller action call:
=form_for #post, :url => {:action => 'delete', :id => #post.id} do |f|
resources :post
match '/delete/:id/', :to => "post#destroy"
root :to => "post#index"