【问题标题】:Rails link_to polymorphic parent, which can have a nested routeRails link_to 多态父级,可以有嵌套路由
【发布时间】:2017-01-18 11:04:52
【问题描述】:

我有评论模型,它是多态的,与项目、用户、更新等可评论模型相关联。我有一个页面,用户可以在其中看到每个用户的评论。我希望每个评论附近都有一个链接,其中包含与该评论关联的对象的地址。 我可以这样写:

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

但这仅适用于非嵌套路由(如用户)。这是我的路线的样子:

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

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

【问题讨论】:

    标签: ruby-on-rails ruby nested polymorphic-associations nested-routes


    【解决方案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)
    

    【讨论】:

    • 我将有一个属于项目的可评论模型更新,我认为最好将更新嵌套。所以无论如何我都必须使用这种“多态路由魔法”。谢谢
    猜你喜欢
    • 2017-09-23
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-22
    相关资源
    最近更新 更多