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

时间:2016-09-10 12:29:39

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

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

    $(".dice-roller").click(function() {
      $("[class^='dot']").remove();
      
      $(".dice").removeClass("num1 num2 num3 num4 num5 num6");

              
      var number1 = Math.floor((Math.random() * 6) + 1);
      var number2 = Math.floor((Math.random() * 6) + 1);
     

      for (var i = 0; i < number1; i++) {
        $(".d1").append("<span class='dot dot" + i + "'></span>");

      }
      if (!$(".d1").hasClass("num" + number1)) {

        $(".d1").addClass("num" + number1);
      }
      for (var i = 0; i < number2; i++) {
        $(".d2").append("<span class='dot dot" + i + "'></span>").addClass("num" + number2);
      }

      if (!$(".d2").hasClass("num" + number2)) {

        $(".d2").addClass("num" + number2);
      }
    });

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

    .dice:first-child{margin-right:20px;}
    .dice{width:100px; height:100px; background:black; border-radius:10px; float:left; position:relative;}
    .dice-roller{position:absolute; left:50%; top:50%; transform:translate(-50%, -50%); cursor:pointer;}
    .dot{width:15px; height:15px; border-radius:100%; background:#fff;display:inline-block; position:absolute;}

    .num1 .dot0{left:50%; top:50%; transform:translate(-50%, -50%);}

    .num2 .dot0{left:15px; top:15px;}
    .num2 .dot1{right:15px; bottom:15px;}


    .num3 .dot0{left:15px; top:15px;}
    .num3 .dot1{right:15px; bottom:15px;}
    .num3 .dot2{left:50%; top:50%; transform:translate(-50%, -50%);}

    .num4 .dot0{left:15px; top:15px;}
    .num4 .dot1{right:15px; bottom:15px;}
    .num4 .dot2{left:15px; bottom:15px;}
    .num4 .dot3{right:15px; top:15px;}

    .num5 .dot0{left:15px; top:15px;}
    .num5 .dot1{right:15px; bottom:15px;}
    .num5 .dot2{left:15px; bottom:15px;}
    .num5 .dot3{right:15px; top:15px;}
    .num5 .dot4{left:50%; top:50%; transform:translate(-50%, -50%);}

    .num6 .dot0{left:15px; top:15px;}
    .num6 .dot1{right:15px; bottom:15px;}
    .num6 .dot2{left:15px; bottom:15px;}
    .num6 .dot3{right:15px; top:15px;}
    .num6 .dot4{right:15px; top:50%; transform:translateY(-50%);}
    .num6 .dot5{left:15px; top:50%; transform:translateY(-50%);}

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

1 个答案:

答案 0 :(得分: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)