Reputation: 48706
i'm having a situation where i have 10 resources(controllers) that correspond to 10 database entries. In particular, it is about buildings. There is a town_center controller, a sawmill controller and more.
I did not want to create a buildings_controller and handle everything there, since each building behaves very differently.
But i have a question on routes and how to handle a particular situation. I would ideally want to have urls like :
/town_center/view
/sawmill/view
This is fine, but i have a fundamental problem. There is no easy way to get the town_center id number from the url. I would of course need this information, in order to get model information about the particular building. Now, one could argue that i can just use this :
/town_center/view/1
/sawmill/view/2
Which seems fine, but poses another fundamental problem, and that is, that i have to specify the id, when i redirect from another controller. Say that i want to redirect to the town_center controller. I would need to do :
redirect_to town_center_url(1)
Which i really don't like, because the id can change anytime in my database and is generally a bad programming practice for sure, very prone to errors.
How would you handle this ? Am i missing a simpler way ?
EDIT :
EXAMPLE ROUTES WITH ID NEEDED
scope :path => '/town_center', :controller => :town_center do
get '/view/:id' => :view, :as => 'town_center'
end
scope :path => '/sawmill', :controller => :sawmill do
get '/view/:id' => :view, :as => 'sawmill'
end
EXAMPLE OF USAGE
Starting from /overview, we see a list of building links like :
/town_center/view/1
/sawmill/view/2
If one clicks on the first, the view action with an :id of 1 is executed. Fine till now. But say that on this view template, there is an action like send_message. Now, this action is like :
def send_message
send_the_message_blah_blah
redirect_to sawmill_url(2)
end
Now, i guess the problem is clear. In order to redirect to the sawmill viewpath, i need to know its id, which means that i would have to make an extra query, for no real reason, like :
def send_message
send_the_message_blah_blah
redirect_to sawmill_url(Building.where(:name=>'sawmill').first)
end
And if i don't include the :id in the url at all, then my view action is just not aware of what building it should refer to.
Upvotes: 1
Views: 75
Reputation: 4383
So if it were me, I would change my routes
up and put a before_filter
in each controller that does the query for you.
So like each one of your routes
would look something like this instead.
scope :path => '/sawmill', :controller => :sawmill do
get '/view' => :view, :as => 'sawmill'
end
then in your SawmillController
you would add the before filter to get the sawmill
from the database.
class SawmillController < ApplicationController
before_filter :get_sawmill
...
private
def get_sawmill
@sawmill = Building.where(:name=>'sawmill').first
end
end
That way anytime someone takes action on a controller, they won't even know that there is a database behind it. The controller does all the legwork AFTER the request is made.
This way you cut the :id
out of your url and _url
methods completely. Meaning just sawmill_url
instead of sawmill_url(1)
, and your url will be /sawmill/view
. Nice and clean!
Upvotes: 1
Reputation: 7545
This makes me think either you don't understand the way rails wants you to do things or that your situation has some special considerations that we are still not aware of:
(edit: looking at your answer history, it seems you know much more about rails than I do so I'm guessing it's the second. please skip to the bottom of this question for my request for you)
redirect_to town_center_url(1) Which i really don't like, because the id can change anytime in my database and is generally a bad programming practice for sure, very prone to errors.
The only solution I know for accessing a resource without some kind of id is through some other contextual information. For example with the devise authentication system, you don't ever use your id anywhere. If you are authenticated, then the server knows who you are and doesn't want to throw your id around unnecessarily in urls or whatever. So similarly if you have someone logged in, you can identify their resources through their session.
example controller (should probably be in a town model actually):
@tc = current_user.town_center
@b = current_user.barracks
view
<%= link_to 'Town Center', @tc %> <%# which still is using some identifier %>
Or if you had a "location" then you could identify the lone town_center through the location similar to above (but now you need the location identifier).
Basically, unless you have some special context, you will need an identifier somewhere.
If that doesn't help, I think you should walk us through one example of how you would like for things to work from zero (user comes to your page. what do they see?) to .... somehow opening a building resource (when does the building originally become available?) to... doing some action with that building.
Upvotes: 0
Reputation: 3532
match '/town_center/view/:id' => 'town_center#view'
if you have a view action in your controller, but why are you fighting the convention. just have:
resources :town_center
you would call town_center(instance_of_a_town_center) which would give you the path
/town_center/1
why do you need the view? its just the get method for an instance of a town_center in the town_center controller.
hope this helps
Upvotes: 0