在Rails中加载嵌套资源的正确方法

时间:2019-04-04 10:44:51

标签: ruby-on-rails

在我们的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>

处理所有嵌套资源的正确方法是什么?

0 个答案:

没有答案