【问题标题】:Rails 4.2+: deep nesting resources when it's required to display data from entire resource chainRails 4.2+:当需要显示来自整个资源链的数据时,深度嵌套资源
【发布时间】:2016-06-09 02:57:10
【问题描述】:

我熟悉嵌套深度不要超过 1 层的准则,并且我理解关于在代码内外尽可能使用最短 URL 的各种讨论。

大多数 StackOverflow 问题和谷歌搜索我已经通过展示不必访问整个链中的所有元素的用例来回答这个问题。

但是,当您必须访问您正在处理的每个页面的更上游的父资源时,您会怎么做?

/{ACCOUNT_SLUG}/applications/{APPLICATION_UUID}/borrower/employments/{UUID}

在处理单个employment 记录时,我必须显示通过ACCOUNT_SLUG 以及application 信息从父account 对象获取的帐户特定信息。从技术上讲,我的borrower 也是一个数据库查询,但由于每个应用程序只有 1 个,所以我不必在 URL 中添加 id/slug。

一般建议是:

/employments/{UUID}

但如果我这样做了,那么在我的控制器代码(和其他地方)中我仍然必须这样做:

@employment = Employment.find_by(uuid: params[:uuid])
@account = @employment.borrower.application.account

所以我必须遍历整个父关联链并执行那些关联数据库查询。如何解决这种从第一个父级到最后一个子级必须保持深层嵌套关联的情况?

1:给所有的孩子添加关联属性

class Employment
  belongs_to :borrower
  belongs_to :application
  belongs_to :account
end

现在我到处都有一堆关联,只是为了走一条清晰的链条。这对我来说似乎是“依赖地狱”?...

2:使用深层嵌套路由; Github 做到了

我注意到 Github 实际上采用了深层嵌套路由:

github.com/{USERNAME}/{REPO}/settings/hooks

虽然不像我的用例那样嵌套深入,但它们仍然将所有内容嵌套在 usernamerepo 下,如果您列出它们的详细 URL,它是:

/github.com/accounts/{USERNAME}/repos/{REPO_NAME}/settings/hooks

是否有人知道 Github 是否有优化这种深度嵌套的方法,或者他们是否只是在每个请求中查找 accountrepo 并占用数据库查询开销(可能没什么大不了的...... )?

3:深度嵌套路由,但创建自己的 URL 助手以保持干净

使用/{ACOUNT_SLUG}/applications/{APPLICATION_UUID}/borrower/employments/{UUID},URL 助手看起来像:

account_applications_borrower_employments_path(@account, @application, @borrower, @employment)

这可以使用一些助手来清理:

def borrower_employment_path(@employment)
  @borrower = @employment.borrower
  @application = @borrower.application
  @account = @application.account
  account_applications_borrower_employments_path(@account, @application, @borrower, @employment)
end

【问题讨论】:

    标签: ruby-on-rails-4 routing nested-resources


    【解决方案1】:

    非常详细的问题。有点晚了,但过去当嵌套资源的问题困扰着我时,我通常需要重新审视我对数据库进行关系建模的方式。

    在您建议的可能解决方案中,考虑到 Rails 框架的固执己见,第 1 项可能是最好的。 Rails 关联非常强大,随着应用程序的扩展,利用它们很有用。

    解决关于模型之间依赖关系的问题:

    没有看到您的架构,我只能猜测,但您的建模可能如下所示:

    Class Account
      has_many :applications
    end
    
    Class Application
      belongs_to :account
      has_one :borrower
      has_one :employment
    end
    
    Class Borrower
      belongs_to :application
    end
    
    Class Employment
      belongs_to :application
      has_one :account, through: :application
    end
    

    这是我对上述信息的最佳猜测。使用此建模,您将能够在控制器操作中执行此操作:

    def action_name
      @employment = Employment.find_by(uuid: params[:uuid])
      @account = @employment.account
    end
    

    您可以添加额外的关联,例如,如果您想这样做: @employment.borrower

    通过添加:

    class Employment
      belongs_to :application
      has_one :account, through: :application
      has_one :borrower, through: :application
    end
    

    为了保持新鲜感,我总是不时读一读这篇文章:

    http://guides.rubyonrails.org/association_basics.html#the-types-of-associations

    尽管 Github 实现了他们的应用程序,但 Rails 通常不鼓励使用重度嵌套路由:

    http://guides.rubyonrails.org/routing.html#nested-resources

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多