views:

36

answers:

1

Hi everyone!

I have three relevant models: Companies, Projects, and Links, and I am trying to create a system where we generate routes according to the Links they create, for example:

www.site.com/the_company's_specific_path/one_of_company's_links

One company has_many :projects, one project has_many :links.

Summary of the structure:

#Company table
company.id
company.path # such as 'Bechtel'

#Project table
project.id
project.company_id

#Link table
link.id
link.link # such as 'railwayproject'
link.project_id
link.company_id # some links may be tied to the company and not one specific project

#Final route generated: www.site.com/bechtel/railwayproject

How can I set up this system so:

  • Part 1 of the route specifies company.path (along the lines of @company = Company.find_by_path(params[:path]))
  • Part 2 finds link (along the lines of @link = Link.find_by_link_and_company_id(params[:link],@company.id))
  • Upon entering this URI/URL the user enters 'show' where they see information on the project or company. (When a link isn't tied specifically to a project we show 'list' instead, displaying all the company's projects.)

I apologize if for any reason the above is unclear. I have tried to explain as best I can! Thanks.

+1  A: 

You should check out the documentation for ActionController::Routing, ActionController::Resources for RESTful routes, and a handy Rails Guide on the topic. There are also a number of Railscasts regarding routes.

Something as simple as map.connect :path/:link, :controller => :companies would work, but it may cause some problems depending on your existing routes and is not RESTful. If it does not cause any conflicts, this would allow you to do what you're asking for.

You can add constraints to the route using the :requirements option to narrow down what is considered a match:

map.company_link :company/:link, :requirements => { :company => /[\w\-]+/, :link => /[\w\-]+/ }

This would only match word and dash ('-') characters in the url, and I believe the default routes will still work properly. I also made it a named route with map.company_link so Rails creates a set of url helpers allowing easy reference to your route: company_link_path(:company => "Bechtel", :link => "railwayproject")

If you want to stick with the REST way of doing this would be:

map.resource :companies do |company|
  company.resources :links
end

/companies/1/links/2 would get passed to the show action of the links_controller with the company and link ids as params. This is explained further in the nested resources section of the previously mentioned Rails Guide. Normally, you would use the :shallow => true option, because the link id of 2 is already unique and does not need to be nested under companies. The real value of the nested route is showing all of the links with /companies/1/links and all other actions going directly to the individual link /links/2.

Awgy
@awgy - As I'm trying to avoid including ids as part of these links, it sounds like what I'm trying to do is inherently not RESTful. I'm working on this now and I'll get back to you on progress shortly. Thank you for such a helpful and detailed response.
sscirrus