I’m working on a Rails 3 app that hosts many projects and every resource within the app is scoped by a project. So wallpapers, videos, polls, etc. belong to a project. Ideally, I want my routes also scoped by a project. It’s easy to configure nested resources that give you routes that look like:
But since everything is scoped by the project name, why don’t I just drop the /projects prefix?
# config/routes.rb scope ':project_name' do resources :videos end
So this gives us params[‘project_name’] in each video action. Now our routes can look like this:
##Access to the Project
You might want access to a @project instance variable in every controller nested within this project scope. If so, you can add this in application_controller.rb:
# app/controllers/application_controller.rb before_filter :load_project protected def load_project project_name = params[:project_name] @project = project_name ? Project.where(:name => project_name).first : nil end
However, a caveat with this is that it breaks simple form_for helpers.
If you had this in your _form.html.haml partial:
# _form.html.haml = form_for @video do |f|
This will now return a RoutingError because the routes expect a :project_name that no longer exists. The fix for this turns out to be a little more complex.
= form_for @video, :url => @video.persisted? ? video_path(@project.name, @video) : videos_path(@project.name) do |f|
Since you can’t rely on the generic form_for, you now need to be explicit about your url. It’s not as terse, but it’ll work for creating and updating a resource.comments powered by Disqus