Routing redirection - ruby-on-rails

I am using Ruby on Rails 3 and I would like to redirect all requests made to a resource (URL) to another resource.
I have the following resources:
<My_app_name>::Application.routes.draw do
resources :users
namespace :users do
resources :user_admins
end
end
What I would like to do is to redirect all requests made to <my_app_name>/users/user_admins/<id> to <my_web_site_name>/users/<id>. How can I do that?
Note: I am using a Single Table Inheritance approach, so that the <id> value will don't change behaviours. That is, the <id> value will be automatically handled from the RoR framework and it will refer to the same resource for both when the URL is <my_app_name>/users/user_admins/<id> or <my_web_site_name>/users/<id>.

You may want to avoid the use of a namespace, and play it like that :
scope "users" do
resources "user_admins", :controller => "users"
end
You'll get those routes :
user_admins GET /users/user_admins(.:format) {:action=>"index", :controller=>"users"}
POST /users/user_admins(.:format) {:action=>"create", :controller=>"users"}
new_user_admin GET /users/user_admins/new(.:format) {:action=>"new", :controller=>"users"}
edit_user_admin GET /users/user_admins/:id/edit(.:format) {:action=>"edit", :controller=>"users"}
user_admin GET /users/user_admins/:id(.:format) {:action=>"show", :controller=>"users"}
PUT /users/user_admins/:id(.:format) {:action=>"update", :controller=>"users"}
DELETE /users/user_admins/:id(.:format) {:action=>"destroy", :controller=>"users"}

Try this in your routes.rb:
match 'users/user_admins/:id' => 'users#show'

Related

Rails - From RESTFul resource to customized routes

This is a design problem that I am trying to figure out. I will explain what I have right now, and what I would like to have:
1. Actual design
I have a defined a resources :users and by doing so I have defined different actions such as new, create and update in the Users controller. This is working as expected by following urls like users/new , users/:id, etc...
Now I want to go one step forward, and I want to be able to do the following...
2. What am I looking for
I want to be able to have a route like this:
users/overview/profile - This should be equivalent to `users/:id` (show action)
users/overview/network - This should be equivalent to users/:id/network (list of networks for that user)
3. My idea
My first idea was to define something like this:
resource :users do
namespace :overview do
resource :networks
end
end
But this would work for urls like: users/:id/overview/networks and I don't want the user id to be shown in the URL. So my questions are:
1 - How can I deal with users/overview/networks instead of users/:id/overview/networks , assuming that I can get the user id from session.
2 - How can I be able to manage URLs like this: users/overview/profile where actually a profile is just the show method of users/:id Right now I have defined all the actions in the users controller and everything is working fine (new,delete,create,update...) I just don't know how to move into that "namespace" overview/profile
I have tried same thing you tried, and it is returning your desired results only, not sure what is your problem. Posting rake routes result here.
users_overview_networks POST /users/overview/networks(.:format) {:action=>"create", :controller=>"overview/networks"}
new_users_overview_networks GET /users/overview/networks/new(.:format) {:action=>"new", :controller=>"overview/networks"}
edit_users_overview_networks GET /users/overview/networks/edit(.:format) {:action=>"edit", :controller=>"overview/networks"}
GET /users/overview/networks(.:format) {:action=>"show", :controller=>"overview/networks"}
PUT /users/overview/networks(.:format) {:action=>"update", :controller=>"overview/networks"}
DELETE /users/overview/networks(.:format) {:action=>"destroy", :controller=>"overview/networks"}
users POST /users(.:format) {:action=>"create", :controller=>"users"}
new_users GET /users/new(.:format) {:action=>"new", :controller=>"users"}
edit_users GET /users/edit(.:format) {:action=>"edit", :controller=>"users"}
GET /users(.:format) {:action=>"show", :controller=>"users"}
PUT /users(.:format) {:action=>"update", :controller=>"users"}
DELETE /users(.:format) {:action=>"destroy", :controller=>"users"}
scope :path => 'users/overview' do
match ':id/profile', :to => 'users#show'
match ':id/network', :to => 'users#network'
end

difference between resource and controller generators

when I do
rails g model user name:string
rails g controller users index create new destroy show
and edit config/routes.rb to add:
resource :users
bundle exec rake routes gives:
users POST /users(.:format) {:action=>"create", :controller=>"users"}
new_users GET /users/new(.:format) {:action=>"new", :controller=>"users"}
edit_users GET /users/edit(.:format) {:action=>"edit", :controller=>"users"}
GET /users(.:format) {:action=>"show", :controller=>"users"}
PUT /users(.:format) {:action=>"update", :controller=>"users"}
DELETE /users(.:format) {:action=>"destroy", :controller=>"users"}
however, when I do
rails g resource users name:string
(which automatically adds resources :users to config/routes.rb)
bundle exec rake routes
I get
users GET /users(.:format) {:action=>"index", :controller=>"users"}
POST /users(.:format) {:action=>"create", :controller=>"users"}
new_user GET /users/new(.:format) {:action=>"new", :controller=>"users"}
edit_user GET /users/:id/edit(.:format) {:action=>"edit", :controller=>"users"}
user GET /users/:id(.:format) {:action=>"show", :controller=>"users"}
PUT /users/:id(.:format) {:action=>"update", :controller=>"users"}
DELETE /users/:id(.:format) {:action=>"destroy", :controller=>"users"}
So my question is,
when I generate a controller how can I get the correct helper methods to make
link_to 'Destroy', instance, :method=> :delete
work?
Because currently it gives an error user_path is not defined.
You should call
rails g controller user index create new destroy show
instead of
rails g controller users index create new destroy show
in order to get resources :users to give you the helpers you want.
The latter causes Rails to assume that users is a singular object, and that resources :users should create what is called a singular resource:
http://guides.rubyonrails.org/routing.html#singular-resources
as a result, user_path is undefined, whereas users_path is defined.
When you use rails g controller and specify the method names, the generator only maps specific routes to the routes file. rails g resource assumes that you want the whole resource functionality and will map resources.
In order to fix this, just go into your routes file and replace the specific mappings with a resources call.
resources :users
What I really wanted was a way of creating a working (with correct delete/show paths) controller for an existing model (as described in the question) but just adding "resource :x" and generating the controller wasn't enough.
I ended up using the scaffold_controller generator. It doesn't create any migrations or models, but it does generate a resource with views and rake paths command shows the correct paths for delete and show to work.
You can run following commands in the console:
$rails g model user name:string
$rails g scaffold_controller User
And add this code line to the file routes.rb:
resources :users

Problem with rails routing

I have the following in my routing config:
resources :users do
resources :apps, :controller => :user_apps
end
rake routes includes the following:
user_apps GET /users/:user_id/apps(.:format) {:action=>"index", :controller=>"user_apps"}
user_apps POST /users/:user_id/apps(.:format) {:action=>"create", :controller=>"user_apps"}
new_user_app GET /users/:user_id/apps/new(.:format) {:action=>"new", :controller=>"user_apps"}
edit_user_app GET /users/:user_id/apps/:id/edit(.:format) {:action=>"edit", :controller=>"user_apps"}
user_app GET /users/:user_id/apps/:id(.:format) {:action=>"show", :controller=>"user_apps"}
user_app PUT /users/:user_id/apps/:id(.:format) {:action=>"update", :controller=>"user_apps"}
user_app DELETE /users/:user_id/apps/:id(.:format) {:action=>"destroy", :controller=>"user_apps"}
However, when I try to access eg user_apps_path(1,2) I get /users/1/apps.2 rather than /users/1/apps/2.
Where am I going wrong?
I'm using rails 3.
The correct route is user_app_path(1,2) The pluralized version goes to the index action, making the second argument the format / extension of the request.

Rails 3 Routing Resources with Variable Namespace

Is it possible to have a variable namespace? I have restful resources like the following:
resources :articles
resources :persons
But I need to scope these inside a variable namespace, such that it responds to URLs of the form:
':edition/:controller/:action/:id'
for example:
/foobar/article/edit/123 or /bazbam/person/edit/345
for each of the resources. Is this possible with the resources method, or must I hand-craft these? I will not know the possible values for :edition ahead of time; these get looked up in a before_filter in my ApplicationController.
Is this all I need to do?
scope ':edition' do
resources :articles
resources :matches
resources :teams
end
UPDATE: When using the scope directive above, I get routes like I want:
articles GET /:edition/articles(.:format) {:action=>"index", :controller=>"articles"}
POST /:edition/articles(.:format) {:action=>"create", :controller=>"articles"}
new_article GET /:edition/articles/new(.:format) {:action=>"new", :controller=>"articles"}
edit_article GET /:edition/articles/:id/edit(.:format) {:action=>"edit", :controller=>"articles"}
article GET /:edition/articles/:id(.:format) {:action=>"show", :controller=>"articles"}
PUT /:edition/articles/:id(.:format) {:action=>"update", :controller=>"articles"}
DELETE /:edition/articles/:id(.:format) {:action=>"destroy", :controller=>"articles"}
matches GET /:edition/matches(.:format) {:action=>"index", :controller=>"matches"}
POST /:edition/matches(.:format) {:action=>"create", :controller=>"matches"}
new_match GET /:edition/matches/new(.:format) {:action=>"new", :controller=>"matches"}
edit_match GET /:edition/matches/:id/edit(.:format) {:action=>"edit", :controller=>"matches"}
match GET /:edition/matches/:id(.:format) {:action=>"show", :controller=>"matches"}
PUT /:edition/matches/:id(.:format) {:action=>"update", :controller=>"matches"}
DELETE /:edition/matches/:id(.:format) {:action=>"destroy", :controller=>"matches"}
teams GET /:edition/teams(.:format) {:action=>"index", :controller=>"teams"}
POST /:edition/teams(.:format) {:action=>"create", :controller=>"teams"}
new_team GET /:edition/teams/new(.:format) {:action=>"new", :controller=>"teams"}
edit_team GET /:edition/teams/:id/edit(.:format) {:action=>"edit", :controller=>"teams"}
team GET /:edition/teams/:id(.:format) {:action=>"show", :controller=>"teams"}
PUT /:edition/teams/:id(.:format) {:action=>"update", :controller=>"teams"}
DELETE /:edition/teams/:id(.:format) {:action=>"destroy", :controller=>"teams"}
I'm now able to reference :edition in my ApplicationController:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :authenticate_user!
before_filter :get_edition
def get_edition
#edition = Edition.first(:conditions => { :FriendlyName => params[:edition] } )
end
end
Now I just want to make sure this is the best way to accomplish this.
Actually, you can just do the following :
my_var = "persons"
resources my_var.to_sym
The to_sym method on a string changes it to a symbol
If you don't know the possible values for edition - then you can't use namespaces which seem like they might have solved this issue.
That said, I'd just handcraft them - your case here seems like the ideal case foregoing resources and going straight to a handcrafted path.

Weird routing error in Rails 3.0

I've been converting my Rails 2.3.9 application to Rails 3.0 and everything has been going well. I've created a lot of routes with the new system so I feel like I know how to do this. However, I recently got a routing error I can't solve.
I have a users resource defined like this:
resources :users do
member do
get 'activate'
get 'edit_password'
post 'update_password'
end
collection do
get 'forgot_password'
post 'send_reset_instructions'
end
end
The failing route is update_password. If I change it to a get method it works. But not when used as a post, with data coming from a form in "edit_password".
This is the error message:
Routing Error
No route matches "/users/31/update_password"
This is the (relevant) output of rake routes:
activate_user GET /users/:id/activate(.:format) {:action=>"activate", :controller=>"users"}
edit_password_user GET /users/:id/edit_password(.:format) {:action=>"edit_password", :controller=>"users"}
update_password_user POST /users/:id/update_password(.:format) {:action=>"update_password", :controller=>"users"}
forgot_password_users GET /users/forgot_password(.:format) {:action=>"forgot_password", :controller=>"users"}
send_reset_instructions_users POST /users/send_reset_instructions(.:format) {:action=>"send_reset_instructions", :controller=>"users"}
users GET /users(.:format) {:action=>"index", :controller=>"users"}
users POST /users(.:format) {:action=>"create", :controller=>"users"}
new_user GET /users/new(.:format) {:action=>"new", :controller=>"users"}
edit_user GET /users/:id/edit(.:format) {:action=>"edit", :controller=>"users"}
user GET /users/:id(.:format) {:action=>"show", :controller=>"users"}
user PUT /users/:id(.:format) {:action=>"update", :controller=>"users"}
user DELETE /users/:id(.:format) {:action=>"destroy", :controller=>"users"}
Finally, this is the output of the web server for that request (webrick):
Started POST "/users/31/update_password" for 127.0.0.1 at 2010-10-14 23:30:59 +0200
SQL (1.5ms) SELECT name
FROM sqlite_master
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
SQL (0.7ms) SELECT name
FROM sqlite_master
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
ActionController::RoutingError (No route matches "/users/31/update_password"):
Rendered /home/jonatan/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.0/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.0ms)
Can you find any logic in this?
I'm using the latest Rails available through gem (3.0.1). At first I did override *to_param* in the User-model to use the username, but the problem is the same no matter what.
I've checked for misspellings in the update_password method of the model, and also made sure it is not private.
I have noticed this as well, only with the POST method and only when using "member", so same as your example, ie:
resources :forum_posts do
member do
post :preview
end
end
will trigger this, but changing it to GET or using collection both work fine, so seems to be a bug with rails routes; I get around this for now by adding the following just above my resources :forum_posts do line:
match '/forum_posts/:id/preview(.:format)', :to => "forum_posts#preview", :as => :preview_forum_post
then everything continues working; easy temporary fix.

Resources