开发者

Better way to route this?

I have a routing issue. my routes currently look like this:

http://localhost:3000/events?category=popular&city=london&country=united-kingdom 

Currently its just looking at resources :events (which is the events controller, index action), and in the index action. I've got a lot of if conditions. Especially, when the app needs to determine which partials to load, based on the query strings.

Is there a better way to refactor this? I am not a big fan of query strings in the URL. And something like this can be solved in routing. Just looking for the right direction. Am looking to have urls like:

/events/london
/events/london/popular
/events/london/united-kingdom
/events/united-kingdom
/events/united-kingdom/popular
/events/london/united-kingdom/popular

The Anti Patterns book, specifically on page 181, suggests creating separate controllers. Which will organize the code further and still keep it RESTFUL.

In theory, I think it is suggesting something like this:

match 'events/:city', :controller => 'events/cities', :action => 'index', :as => 'by_city', :via => :get
match 'events/:city/:category', :controller => 'events/cities_and_categories', :action => 'index', :as => 'by_city_and_category', :via => :get
match 'events/:city/:country', :controller => 'events/cities_and_countries', :action => 'index', :as => 'by_city_and_country', :via => :get
match 'events/:country', :cont开发者_JAVA技巧roller => 'events/countries', :action => 'index', :as => 'by_country', :via => :get
match 'events/:country/:category', :controller => 'events/countries_and_categories', :action => 'index', :as => 'by_country_and_category', :via => :get
match 'events/:city/:country/:category', :controller => 'events/cities_and_countries_and_categories', :action => 'index', :as => 'by_city_and_country_and_category', :via => :get

OR, are filtered terms REALLY supposed to be in query string format?

If you have a suggestions / better approach. Do mention.


First off, some cleaner routes that are more canonical:

resources :events do
  get '/:country(/:city)(/:category)' => 'events#filtered', :on => :collection, :constrain => { :category => %w{ popular legal_marijuana } }
end

I've made the country required. There are too many ambiguous city names, and unless you want to do a lot of poking to determine segment is what, this is just more straightforward. The city is optional, and so is the category.

Unless I've mistaken something here, this will constrain the category to either "popular" or "legal_marijuana" (but not both, so Amsterdam is out, haha).

All of these routes go to a single filtered action on your events controller. Don't bother trying to keep this resourceful unless it makes sense for every country and city to be a resource for your application. As long as this responds to a GET request, and it retrieves a collection of records, it's not very far out of the bounds of the REST principals (interesting note, the new and edit actions in Rails don't adhere strictly to REST either).

This action will need to do a bit of poking at params to see whether or not you have a city or category. You can use something like this to help you out:

@event = Event.where(:country => params[:country])
@event = @event.where(:city => params[:city]) if params[:city]

[For some reason this doesn't look right to me. I can't think straight. I'm sure that this is a mess. Someone please save me.]

But yeah, that's the idea.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜