Is it possible to specify a named route within a resourceful route? - ruby-on-rails

I'm just upgrading my app to Rails 3 and as I have to rewrite my routing anyway, I'm taking some time to improve my named routes.
I have an invoices controller which has a trash action (/invoices/trash lists all invoices in trash). I want to access this through a named route (i.e. trash_url) for simplicity in my views.
I can achieve this easily enough with the following
match "/invoices/trash" => "invoices#trash", :as => :trash
What I want to know is if there is a way of doing this within the block where I define the routes for my invoice controller. I have tried the following and it doesn't work.
resources :invoices do
collection do
get :trash, :as => :trash
end
end
Is what I am trying to do possible or do I have to define my named route outside of this block?
Thanks.

The method you list (shown below) works fine for me, it generates trash_invoices_path and trash_invoices_url helper methods.
resources :invoices do
collection do
get :trash, :as => :trash
end
end
You can make methods in your application controller named trash_url and trash_path that just call and return the path from the generated methods mentioned above if you have a need to use those specific method names instead of the generated ones.

Related

How to organize similar routes for multiple Rails users?

Let's say I have an Accountant < User model, and a Worker < User model. They both need to have pages like 'Settings', 'Dashboard', etc.
Right now the paths are assigned and explicitly defined in routes.rb:
resources :accountants
get '/accountant/dashboard' => 'accountant#dashboard'
get '/accountant/dashboard/:date' => 'accountant#dashboard'
get '/accountant/settings' => 'accountant#settings'
resources :workers
get '/worker/dashboard' => 'worker#dashboard'
get '/worker/dashboard/:date' => 'worker#dashboard'
get '/worker/settings' => 'worker#settings'
Saving the "home" dashboard path in a session / as application level helper methods which rely on current user class both don't seem very Ruby-esque. Is there an alternative to this in Rails 4?
The better way for this situation is NameSpace, Rails provide us something called namespace and you can use it in the routes for generate different routes for different views in your case maybe works something like that:
namespace :accountants do
get 'dashboard'
get 'dashboard/:date'
get 'settings'
end
namespace :workers do
get 'dashboard'
get 'dashboard/:date'
get 'settings'
end
and that will generate a routes like that:
localhost:3000/accountants/1/dashboard
localhost:3000/workers/1/settings
it's just and example you always can read the official documentation about it, but it's a good way for organize your different routes thinking in the scalability.
Another option is using roles to manage the different users you have because of you extend of user model is not scalable with the time and it's going to be a little confuse in the future read this code
Regards !

Use a nested Resource or have a collection on the resource

I have 2 Models, 'Device' and 'DeviceActivity' where Device has many Device Activities. Now if i would use regular resource nesting i would end up with something like
/devices/1/activities
or
/devices/1/activities/1
What i want is to access
/devices/activities
where i want to show all activities of all devices, like an activity stream. Is creating a collection on the Devices resource the right way?
This is the solution
resources :devices do
collection do
resources :activities, :controller => 'device_activities'
end
end
so you want a GET /devices/activities so far as i read resourceful routing this is not covered but you may define this in the routing yourself in the routes like
match "devices/activities" => 'devices#activities', :as => :devices_activities
so you only need to implement the activities method in your DevicesController with the view respectively

Rails routes, how to specify this member proper

I currently have some routes that look like the following:
resources :contests do
member do
get :enter
end
end
This allows me to do an HTTP GET on a URL that looks like /contests/5/enter. Now, a user can go in, fill in some forms, and be able to submit an entry to the contest. So I'd also like to be able to POST to this URL. I tried doing the following:
resources :contests do
member do
get :enter
post :enter
end
end
This posts to the same controller#action as the GET member that I have specified, so it's not really intuitive. I'd like to be able to direct it to a separate action if at all possible. What's the best way of doing that? I am using Ruby on Rails 4 beta currently.
** UPDATE **
I tried the following but I get an ArgumentError exception when I start the server:
resources :contests do
member do
get :enter
post :enter => "contests#create_entry"
end
end
You can do something like this:
resources :contests do
member do
get :enter
post '/enter', to: "contests#create_entry", as: "create_entry"
end
end
However i agree with Ola Tuvesson, you should definitely create a new controller and routes for entries, even though you may not have a model, similiar to how you often have a session controller for login and logout. Something like this:
resources :contests do
resources :entries, only: [:new, :create]
end
You can specify the controller/action you want to point a route at.
get :enter => "controller#get_enter"
post :enter => "controller#post_enter"
I would suggest you make the entries for a contest a child model of contests. That would give you all the CRUD methods on entries and your routes would simply be:
resources :contests do
resources :entries
end
A GET of /contests/5/entries/new will give you the form for adding an entry and when this POSTs to /contests/5/entries it would create a new entry. It also makes it easy to list all entries for a competition etc. You can easily create the controller, model and the associated views with the scaffold generator, for example:
rails g scaffold Entry contest:references name:string email:string
The references column type tells the generator to link Contests to Entries in a one to many relationship. Job done.
Edit:
If you still want to rename your routes, here's how:
http://guides.rubyonrails.org/routing.html#overriding-the-named-helpers
HTH

Rails 3 routes to wrong controller

I wanted to create a new action and I call it "showemployees". That's what I did already:
-> in the controller:
def showemployees
end
-> creating app/views/employees/showemployees.html.erb
-> in config/routes
match "/employees/showemployees" => "employees#showemployees"
I thought this is enough for opening the showemployees.html.erb now via localhost:3000/employees/showemployees , but it seems like Rails still routes through the show action (from resources :employees) and doesn't take the showemployees-action, because it tells me
ActiveRecord::RecordNotFound in EmployeesController#show
Couldn't find Employee with ID=showemployees
What do I need to change so Rails takes the showemployees-action?
the source code of my route:
System::Application.routes.draw do
match "/employees/showemployees" => "employees#showemployees" #für showemployees.html.erb
root :to => "employees#index"
resources :course_to_dos
resources :current_qualifications
resources :expected_qualifications
resources :skills
resources :employees
resources :positions
resources :admin
end
try to walk by Rails-way, if you want to get collection, use the collection
resources :employees do
collection do
get :showemployees
end
end
If you post your full routes file we can make a definitive call, but based on the error message, it looks like you have a broader route definition mapping to employees#show defined above this route in such a way that it is getting matched.
Routes are evaluated in the order they are defined, so if you have a very broad route pattern defined above a narrow one, your narrow route will never be called.
edit: you'll want to take the forward slash out of your route and add the showemployees to the actual URL, so that it reads
match "employees/showemployees" => "employees#showemployees"

How to map a new CRUD action in 'routes.rb'?

In my 'routes.rb' file I have this code:
resources :users
that maps my user's controller like this.
If I want to map the "reset" view/url for users (Path: /users/reset) what code I have to insert in the 'routes.rb' file?
Two options - I'm assuming you're just going to act on the session user so you don't need to pass in an id to operate on? If so, you'll need to make a few additional changes...
Use an explicit route:
match "/users/reset" => 'users#reset', :as => 'reset_user'
The 'as' part is optional.
Add a new route that operations on a 'collection'. This gets you your route but feels like a hack, I wouldn't recommend it.
resources :users do
collection do
get 'reset'
end
end
Do this:
resources :user do
member do
get 'reset'
end
end
See this section in the Rails Guide you referred to.

Resources