在路径中找到上一级资源(嵌套资源) - Rails

时间:2017-04-24 01:29:02

标签: ruby-on-rails routes rails-routing

我正在构建一个具有以下资源设置的应用程序:

User
  Team
    Invite
    Project
      Invite

users有一个teamteams有许多projects。可以邀请users加入teams级别(并且可以访问projects拥有的任何teams)或project级邀请{}只允许被邀请者访问单个项目。)

我正在尝试设置邀请以动态查找它的父资源(即:TeamProject)。据我了解,最好的方法是看路径。目前路径看起来像:

  • /teams/:id/invites/
  • /teams/:id/projects/:id/invites

是否有可能看到一个"嵌套级别"从路径中的当前资源返回以在控制器操作中查找父资源(例如:invites#new)?

谢谢!

澄清

我希望能够为invitesteams资源使用相同的projects代码。调用invites#new操作时,它会检查路径以查看调用了哪个资源。如果路径为/teams/:id/invites/,则会返回team然后我可以:id找到,如果路径为/teams/:id/projects/:id/invites,则会再次返回project ,然后我可以通过:id找到。

这可能吗?

2 个答案:

答案 0 :(得分:0)

当路线是:

/teams/:team_id/invites/new //note that it should be team_id, not :id,

/teams/:team_id/projects/:project_id/invites/new

你可以随时检查这些参数的嵌套。如果

PARAMS [:PROJECT_ID] .present?

然后你在/ teams /:team_id / projects /:project_id / invites route下,invitable_type应该是Project。否则,它应该是/ teams /:team_id / invites /,并且invitable_type应该是Team。

答案 1 :(得分:0)

首先,你不应该嵌套多个级别。

  

经验法则资源不应嵌套超过1个级别   深。集合可能需要由其父级确定范围,但需要具体   成员总是可以通过id直接访问,而不应该需要   范围界定(除非由于某种原因,id不是唯一的)    - Jamis Buck

您的路径应如下所示:

concerns :inviteable do
  resources :invites, shallow: true
end

resources :teams, concerns: :inviteable
resources :projects, concerns: :inviteable

这提供了所需的所有上下文!添加更多嵌套只会增加膨胀和过度复杂,并使API变差。

要为嵌套的多态资源创建可重用控制器,您可以使用路由关注点:

class InvitesController < ApplicationController

  before_action :set_parent, only: [:new, :create, :index]

  # GET /teams/:team_id/invites/new
  # GET /projects/:team_id/invites/new
  def new
    @invite = @parent.invites.new
  end

  # GET /teams/:team_id/invites
  # GET /projects/:team_id/invites
  def index
    @invites = @parent.invites
  end

  # POST /teams/:team_id/invites
  # POST /projects/:team_id/invites
  def create
    @invite = @parent.invites.new(invite_params)
    # ...
  end

  # ...

  private

  def parent_class
    if params[:team_id]
      Team
    elsif params[:project_id]
      Project
    end
  end

  def parent_param
    params[ parent_class.model_name.singular_route_key + "_id" ]
  end

  def set_parent
    @parent = parent_class.find(parent_param)
  end 
end 

然后,您可以为邀请设置控制器,以检查父项是否存在:

class A
end