【问题标题】:Simple Acts_as_tree with nested_resources具有嵌套资源的简单 Acts_as_tree
【发布时间】:2012-04-21 04:31:24
【问题描述】:

使用 Rails 3.1.1 和 gemacts_as_tree。我已经用谷歌搜索了这个问题并在 SO 上检查了类似的问题(答案太旧或不相关)。

我有一个名为 items 的模型,它的路线今天看起来像:

  resources :articles, :path => '', :only => :show 
  resources :articles, :path => 'articles', :except => :show

我有三篇文章:“book”、“chapter1”和“chapter2”。 book 是第 1 章和第 2 章的父级。

今天,我每篇文章的路径是:host.com/book、host.com/chapter1 和 host.com/chapter2。我希望 url 路径是 host.com/book/chapter1 和 host.com/book/chapter2 ,即嵌套路由。

如何以简洁明了的方式创建它?

基本上,我想要一个路径为 host.com/:parent_id/:parent_id/:id 和 N 个 :parent_id。几乎是 Wordpress 文章的路由方式。

我不相信路由 globbers 是解决方案,但我可能错了。 host.com/:id 和 host.com/foo/bar/:id 似乎给出了相同的结果,这将导致重复的内容。

【问题讨论】:

    标签: ruby-on-rails nested-routes acts-as-tree


    【解决方案1】:

    A)

    如果您有路由解决方案并且唯一的问题是您担心重复的内容问题,您可以考虑将<link rel="canonical" href="..."> 添加到从这些请求生成的页面中。但它并不是万无一失的,因为 Google 认为这是一个建议。

    不确定路由 globbers 解决方案是否会负责生成带有父 ID 的 URL。

    B)

    您不需要父 ID 来执行路由,对吗?您只想将它​​们包含在 URL 中并像使用 example.com/chapter1 这样的 URL 一样路由这些请求,对吗?

    如果您考虑的解​​决方案不是纯粹在 Rails 级别,那么在 Rails 处理之前重写这些请求的 URL 以使 /:parent_id/:parent_id/:id 变为 /:id 怎么样?如果有一个静态前缀会更容易,比如/articles/:parent_id/:parent_id/:id。

    我想您需要编写一些帮助程序来生成带有父 ID 的 URL,以链接到这些资源。

    重复内容

    无论哪种方式,您都需要生成包含父 ID 的 URL,因此如果您仅使用这些 URL 链接到这些资源,则可能不太可能出现重复内容问题。

    【讨论】:

    • 我想我将不得不选择 A。但我不能说我理解你对 B 的意思。但你是对的,我只需要 parent_id 进行路由。但是,/parent_id/ 上的文章也是一篇文章。
    • 其实我是说你不需要 parent_id 来路由,对吗?你想让/:parent_id/:parent_id/:id 路由到/:id 现在的同一篇文章,对吧?如果您仅使用包含父 ID 的 URL 链接到这些资源,则您不必担心重复的内容。在我看来,您需要的部分是 1) 生成带有父 ID 的 URL,2) 让这些 URL 路由到正确的控制器、操作和文章。对于#1,我认为您需要编写一些帮助程序,除非 Acts_as_tree 包含生成此类路径的方法。
    • 对于#2 / B,如果只是最终的文章ID实际用于路由,您可能会在Rails甚至路由请求之前重写URL,并使用/:id上的资源路由。 Web 服务器(例如 Apache mod_rewrite)、Rack 和 Rails 级别可能有解决方案。此时,如果您仍然担心重复的内容,您可以将诸如 /:id(其中:id 用于有父母的文章)之类的 URL 重定向到 /:parent_id/:id,但您必须实现一些额外的逻辑以区分这种情况和/:id,其中:id 用于没有父母的文章。
    【解决方案2】:

    您有三个“文章”...“书”、“章节 1”和“章节 2”都代表相同的“资源”,名为“文章”。不能嵌套相同的“资源”。如果您需要嵌套路由,则必须分别定义父资源和子资源。以下代码spinet可能会对您有所帮助

    class Book < ActiveRecord::Base
      has_many :chapter
      accepts_nested_attributes_for :chapters
    end    
    
    class Chapter < ActiveRecord::Base
      belongs_to :book
      acts_as_tree :parent_id
    end
    

    【讨论】:

      【解决方案3】:
      match '*p1/*p2/*p3/.../*pn' => 'articles#show'
      

      ... 不是字面的,只需定义所需数量的参数即可。

      URL:
      host.com/book/chapter1
      params[:p1] = 'book'
      params[:p2] = 'chapter1'
      params[:p3] = nil
      
      
      URL:
      host.com/book/chapter1/section2/sentence4
      params[:p1] = 'book'
      params[:p2] = 'chapter1'
      params[:p3] = 'section2'
      params[:p4] = 'sentence4'
      params[:p5] = nil
      

      那必须是您的最后一条路线。

      我认为它也会使任何包罗万象的路由无法运行,但它们现在在 Rails 3 的默认 routes.rb 中被注释掉了,如果你使用它们,你必须手动指定通常由旧路由处理的所有路由风格包罗万象的路线。

      而且,如果您有一个名为articles 的控制器,那么您永远不可能拥有与所有控制器相同的标题为“articles”的书,为了安全起见,您可能必须重命名所有控制器,即articles 变为X_articles。那时你永远不可能有一本名为 X_articles 的书,等等......

      完全未经测试。

      【讨论】:

      • 谢谢,但我不能这样做,因为没有固定的关卡数量。有些是 host.com/article,有些是 host.com/parent-article/article
      【解决方案4】:

      您想要做的是将 Rails 用于它不是为它设计的东西。无论您在这里得到什么答案,它要么不是 RESTful、DRY,要么与 Active Record 一起使用没有意义。考虑重新构建您的想法,或将您的应用程序带到另一个平台,如果为时不晚。

      【讨论】:

      • 我会说 Rails 实现 REST 的方式不是 RESTful,而且在某些方面它是一个混蛋,只要他遵守 REST 的基本原则(即 GET 不会修改资源),他的 RESTful 足以获得一些好处,(即负载均衡器可以将他的 URL 指向数据库的只读复制。)我认为他没有过度嵌套,他没有嵌套他的资源,他只是想得到他的 URL 看起来有点像。我认为在这种情况下放弃 Rails 是没有必要的。我认为也许他应该放弃强制 URL 看起来像“树状”的想法
      • 我不明白这会是一件多么困难的事情。所有的博客都是这样组成的,而且 url 反映了文章的内部树结构是完全合理的。
      猜你喜欢
      • 2011-08-23
      • 2014-08-02
      • 1970-01-01
      • 2021-07-21
      • 1970-01-01
      • 2011-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多