Простое дерево Acts_as_tree с вложенными_ресурсами

Используя Rails 3.1.1 и гем act_as_tree. Я погуглил эту проблему и проверил подобные вопросы здесь, в SO (ответы слишком старые или неактуальные).

У меня есть модель под названием статьи с маршрутом, который сегодня выглядит так:

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

У меня есть три статьи: "книга", "глава1" и "глава2". Где книга является родительской для главы 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.

Я не верю, что маршрутные глоберы - это решение, но я могу ошибаться. Кажется, он дает одинаковый результат для host.com/:id и host.com/foo/bar/:id, что приведет к дублированию контента.


person Christoffer    schedule 08.04.2012    source источник


Ответы (4)


A)

Если у вас есть решение для маршрутизации и единственная проблема с ним заключается в том, что вас беспокоят проблемы с дублированием контента, вы можете рассмотреть возможность добавления <link rel="canonical" href="..."> к страницам, созданным на основе этих запросов. Однако это не является пуленепробиваемым, поскольку Google считает это предложением.

Не уверен, что решение globbers маршрута позаботится о создании URL-адресов с родительскими идентификаторами.

B)

Вам не нужны родительские идентификаторы для выполнения маршрутизации, верно? Вы просто хотите включить их в URL-адреса и направить эти запросы так же, как если бы использовали URL-адреса типа example.com/chapter1, верно?

Если вы рассматриваете решение не только на уровне Rails, как насчет перезаписи URL-адресов в этих запросах, чтобы /:parent_id/:parent_id/:id становилось /:id до того, как Rails их обработает? Было бы проще, если бы был статический префикс, например /articles/:parent_id/:parent_id/:id.

Я предполагаю, что вам нужно написать несколько помощников для создания URL-адресов с родительскими идентификаторами для ссылки на эти ресурсы.

Дублированный контент

В любом случае вам нужно будет сгенерировать URL-адреса, которые включают родительские идентификаторы, поэтому проблемы с дублированием контента, вероятно, не слишком вероятны, если вы ссылаетесь только на эти ресурсы, используя эти URL-адреса.

person JMM    schedule 17.04.2012
comment
Думаю, мне придется пойти с А. Хотя не могу сказать, что понимаю, что вы имеете в виду под Б. Но вы правы, мне нужен только parent_id для маршрутизации. Однако статья в /parent_id/ тоже является статьей. - person Christoffer; 18.04.2012
comment
На самом деле, я имел в виду, что вам не нужен parent_id для маршрутизации, верно? Вы хотите, чтобы /:parent_id/:parent_id/:id направлял к той же статье, что и /:id, правильно? Если вы ссылаетесь только на те ресурсы с URL-адресами, которые включают родительские идентификаторы, вряд ли вам придется беспокоиться о дублирующемся контенте. Мне кажется, что вам нужны следующие части: 1) создание URL-адресов с родительскими идентификаторами, 2) получение их для маршрутизации к правильному контроллеру, действию и статье. Я думаю, что для № 1 вам нужно будет написать несколько помощников, если только Acts_as_tree не включает методы для создания таких путей. - person JMM; 18.04.2012
comment
Для # 2 / B, если только последний идентификатор статьи фактически используется в маршрутизации, вы потенциально можете переписать URL-адрес еще до того, как Rails направит запрос, и использовать маршрутизацию ресурсов на /:id. Могут быть решения на уровне веб-сервера (например, Apache mod_rewrite), Rack и Rails. В этот момент, если вы все еще беспокоитесь о дублирующемся контенте, вы можете перенаправить URL-адреса, такие как /:id (где :id для статьи, у которой есть родители) на /:parent_id/:id, но вам придется реализовать некоторую дополнительную логику, чтобы различать этот случай и /:id где :id для статьи, у которой нет родителей. - person JMM; 18.04.2012

У вас есть три "статьи"... "книга", "глава 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
person suvankar    schedule 13.04.2012

match '*p1/*p2/*p3/.../*pn' => 'articles#show'

... не является буквальным, просто определите столько параметров, сколько вам нужно, вплоть до n.

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

Это должен быть ваш ПОСЛЕДНИЙ маршрут.

Я думаю, что это также сделало бы любые перехватывающие маршруты неработоспособными, но теперь они закомментированы в файле route.rb по умолчанию в Rails 3. Если вы их используете, вам придется вручную указать все маршруты, которые обычно обрабатываются перехватывающими маршрутами старого стиля. .

И, если у вас есть контроллер с именем article, у вас никогда не будет книги с одинаковым названием «статьи» со всеми вашими контроллерами. Чтобы быть в безопасности, вам, вероятно, придется переименовать все ваши контроллеры, т. е. статьи станут X_articles. Тогда у вас никогда не будет книги под названием X_articles и так далее...

Совершенно не проверено.

person RadBrad    schedule 15.04.2012
comment
Спасибо, но я не могу этого сделать, потому что нет установленного количества уровней. Некоторые из них будут иметь вид host.com/article, а некоторые — host.com/parent-article/article. - person Christoffer; 18.04.2012

То, что вы хотите сделать, это использовать Rails для чего-то, для чего он не создан. Независимо от того, какой ответ вы получите здесь, он либо не будет RESTful, DRY, либо не имеет смысла для использования с Active Record. Рассмотрите возможность реструктуризации своей идеи или переносите свое приложение на другую платформу, если еще не поздно.

person Kyle Macey    schedule 15.04.2012
comment
Я бы сказал, что это не RESTful, как Rails реализует REST, и это в некотором роде искажение, пока он придерживается основных принципов REST (т.е. GET не изменяет ресурс), он достаточно RESTful, чтобы получить некоторая выгода (например, балансировщик нагрузки может направить свой URL-адрес на репликацию базы данных только для чтения.) Я не думаю, что он слишком вложен, он не вкладывает свои ресурсы, он просто пытается заставить его URL-адреса выглядеть определенным образом. Думаю, отказываться от рельсов в данном случае не нужно. Я думаю, что, возможно, ему следует просто отказаться от идеи заставить URL-адреса выглядеть «древовидными». - person RadBrad; 16.04.2012
comment
Я не понимаю, как это может быть так сложно сделать. Все блоги составлены таким образом, и вполне логично, что URL-адреса отражают внутреннюю древовидную структуру статей. - person Christoffer; 18.04.2012