I made a nested r开发者_开发问答oute in a Ruby on Rails 3 project. with the following routing:
resources :companies do
resources :projects
end
now I can get to the project contoller's index method via example.com/projects/id or example.com/companies/id/projects/id, but both pages display exactly in the same manner. How can I change the projects page in the second example to only show projects that are associated with that company?
I would change how you scope the finds. Rails 3 is beautiful for allowing you to do this because just about everything is scope'able.
Firstly in your controller I would find the parent resource using something like this:
before_filter :find_company
# your actions go here
private
def find_company
@company = Company.find(params[:company_id]) if params[:company_id]
end
This should be fairly straight forward: Find a Company
record that has an ID that matches the one passed in from the nested route. If it's not nested, then there's not going to be a params[:company_id]
so therefore there wouldn't be a @company
variable set.
Next, you want to scope the project find, depending on whether or not a @company
is set. This is easy too. Right under the first before_filter
, put this one:
before_filter :scope_projects
Then define the method for it underneath the find_company
method like this:
def scope_projects
@projects = @company ? @company.projects : Project
end
Now you're probably thinking "WOAH". I know. Me too.
Now wherever you would reference either the projects
association or the Project
class, use @projects
instead. By the power of this scope_projects
method, your app will know whether or not you mean "all projects, ever" or "all projects, ever, that are in the specified company".
Now when you get to the views, you could do something like this:
<h1><% if @company %><%= @company.name %>'s<% end %> Projects</h1>
You could even move it into a helper:
def optional_company
if @company
@company.name + "'s"
end
end
And turn that ugly hunk-o-logic into this:
<h1><%= optional_company %> Projects</h1>
Modify as required.
Hope this has been helpful.
With the power of inherited_resources you can have optional nesting with the following controller:
class ProjectsController < InheritedResources::Base
belongs_to :company, :optional => true
end
精彩评论