I have a Vehicle model:
Routes:
map.resources :vehicles, :has_many => :suppliers
Everything works great, but Vehicle has a boolean attribute is_truck. I want to make an Alias so I can get the same resources filtering only trucks, I tried with:
Routes:
map.trucks '/trucks', :controller => :vehicles, :action => :index, :is_truck => true
map.trucks '/trucks/by_supplier/:supplier', :controller => :vehicles, :action => :index, :is_truck => true
The first one works well, but when I search within a Form the second doesn't work and searches all suppliers.
Controller:
class VehiclesController
def index
if params[:supplier]
@vehicles = Vehicle.all :conditions => { :is_truck => params[:is_truck] }
else
@vehicles = Vehicle.all
end
end
...
end
Search Form:
<% form_for :truck, :url => {:controller => :trucks, :action => :index}, :html => {:method => :get} do |f| %>
<% f.text_field :search %>
<% f.submit 'Search Trucks' %>
<% end %>
Is it possible to map.resources as an alias ?
I found a cleaner way to do it, but Search is still broken under a specific supplier:
# Show all vehicles
map.connect '/vehicles/supplier/:supplier', :controller => :vehicles, :action => :index
map.resources :vehicles
# Only show trucks
map.connect '/trucks/supplier/:supplier', :controller => :vehicles, :action => :index, :is_truck => true
map.resources :vehicles, :as => 'trucks', :requirements => { :is_truck => true }
Resource: http://api.rubyonrails.org/classes/ActionController/Resources.html
Just amend your routes in the following way:
map.resources :vehicles, :has_many => :suppliers,
:collection => { :trucks => :get }
And check rake routes
for the routes this generates. It will allow you to list vehicles which are trucks:
trucks_vehicles GET /vehicles/trucks(.:format)
{:controller=>"vehicles", :action=>"trucks"}
So you now just need to add a new action called "trucks" which works similar to "index". Forms should keep track on it's own (via form fields) if you create a truck or another vehicle. Don't try to trick around with rails routing, which usually would mean your app design is flawed which will get you into trouble later.
You may take a look at STI (single table inheritance: one table stores multiple classes of vehicles). Another way would be to create a trucks controller which inherits from the vehicles controllers and overwrites just some methods like so:
class TrucksController < VehiclesController
def new
@is_truck = true
super
end
...
end
or
class TrucksController < VehiclesController
before_filter :this_is_a_truck
...
private
def this_is_a_truck
@is_truck = true
super
end
end
Update: Here's another one (given you have a is_truck column):
class TrucksController < VehiclesController
around_filter :with_truck_scope
...
private
# Scope every active record access with an is_truck condition
# you may want to put this directly into the model to get rid of the .send
# method and directly access "Vehicle.with_truck_scope &block" here
def with_truck_scope(&block)
Vehicle.send :with_scope, :find => { :conditions => "is_truck = 1" },
:create => { :is_truck => 1 }, &block
end
end
But I recommend really first to try out going with the :collection
and :member
parameters of Rails' routing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With