首页 文章

Rails link_to多态父级,可以有一个嵌套路由

提问于
浏览
0

我有Comment模型,它与可评论模型(如Project,User,Update等)的多态关联 . 我有一个页面,用户可以看到每个用户的评论 . 我希望每条评论附近都有一个链接,其中包含与此评论关联的对象的地址 . 我可以这样写:

link_to 'show on page', Object.const_get(c.commentable_type).find(c.commentable_id)

但这只适用于非嵌套路由(如User) . 这是我的路线的样子:

resources :users do
  resources :projects, only: [:show, :edit, :update, :destroy]
end

所以当我需要一个指向Project页面的链接时,我会收到一个错误,因为我需要一个像user_project_path这样的链接 . 如何让Rails生成正确的链接?不知何故,我必须找出这个对象的路由是否嵌套,并找到嵌套的路由的父路由

1 回答

  • 1

    你可以使用一点多变的路由魔法 .

    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)
    

相关问题