您可以使用一些多态路由魔法。
module CommentsHelper
def path_to_commentable(commentable)
resources = [commentable]
resources.unshift(commentable.parent) if commentable.respond_to?(:parent)
polymorpic_path(resources)
end
def link_to_commentable(commentable)
link_to(
"Show # {commentable.class.model_name.human}",
path_to_commentable(commentable)
)
end
end
class Project < ActiveRecord::Base
# ...
def parent
user
end
end
link_to_commentable(c.commentable)
但感觉很脏。您的模型不应该意识到路由问题。
但解决此问题的更好方法可能是取消嵌套路由。
除非资源是纯粹嵌套的并且在其父上下文之外没有意义,通常最好使用最少的嵌套并考虑资源可能具有不同的表示形式。
/users/:id/projects 可以显示属于用户的项目。而/projects 将显示应用程序中的所有项目。
由于每个项目都有自己的唯一标识符,我们可以在不嵌套的情况下路由单个路由:
GET /projects/:id - projects#show
PATCH /projects/:id - projects#update
DELETE /projects/:id - projects#destroy
这让我们可以在不了解“父”资源的情况下使用多态路由,并且通常会带来更好的 API 设计。
考虑这个例子:
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
resources :projects
resources :users do
# will route to User::ProjectsController#index
resources :projects, module: 'user', only: [:index]
end
end
class ProjectsController < ApplicationController
def index
@projects = Project.all
end
# show, edit, etc
end
class User::ProjectsController < ApplicationController
def index
@user = User.joins(:projects).find(params[:user_id])
@projects = @user.comments
end
end
这可以让我们通过以下方式从评论链接到任何项目:
link_to 'show on page', c.commentable
以及任何用户的项目:
link_to "#{@user.name}'s projects", polymorpic_path(@user, :projects)