在我们的Rails应用程序中,我们有一些相当深的嵌套路由。在如何最好地加载控制器中的资源方面引起了一些困惑。
例如,我们可能具有以下设置:
/clients/:client_id/products/:product_id/builds/:build_id/downloads/:id
在下载控制器中,我们可能会:
class DownloadsController < ApplicationController
before_action :assign_instance_variables
def index
@downloads = Download.where(build_id: params[:build_id])
end
def show
@download = Download.find(params[:id])
end
private
def assign_instance_variables
@client = Client.find(params[:client_id])
@product = Product.find(params[:product_id])
@build = Build.find(params[:build_id])
end
end
但是我们注意到,这实际上允许您将下载的ID从另一版本更改为一个,即使它没有关联,也可以很好地加载它,因为我们没有考虑关联...
因此我们将其重构为:
class DownloadsController < ApplicationController
before_action :assign_instance_variables
def index
@downloads = @build.downloads
end
def show
@download = @build.downloads.find(params[:id])
end
private
def assign_instance_variables
@client = Client.find(params[:client_id])
@product = @client.products.find(params[:product_id])
@build = @product.builds.find(params[:build_id])
end
end
这意味着将对照父对象检查整个嵌套中的所有ID,如果有任何失败,它将引发ActiveRecord :: NotFound。
我们还考虑过这样做:
@download = Download.find(params[:id]
@build = @download.build
@product = @build.product
@client = @product.client
因此,我们只进行一次查找,然后遵循链备份,但这会带来一个问题,即除了下载一个之外,没有其他ID被使用,这意味着您可以输入任何内容,并且该URL仍被视为有效...... / p>
处理所有嵌套资源的正确方法是什么?