Страницы

Поиск по вопросам

четверг, 11 июля 2019 г.

Rails 1 контроллер для 2х моделей?

Жили-были 2 модели с 2мя контроллерами Category и Subcategory. Subcategory были вложены в Category.И url были у них вида categories/category-title, categories/category-title/subcategory-title соответственно. И все было замечательно. Но пришли СЕОшники и сказали что не кошерен url более 2х уровней. И повелели сотворить url 2х уровневый вида catalog/category-title и catalog/subcategory-title.
Все бы хорошо но как быть с show в контроллере? Как определить к какому ресурсу отнести?
Насколько данный метод зело неправилен? Есть ли на свет белом более правильные методы?


Ответ

URL — Uniform Resource Locator. Поэтому когда речь идёт об изменении урлов, речь идёт о переносе ресурсов.
В данном случае вас просят сделать урлы вида:
/categories/:title
...и вы сталкиваетесь с проблемой, что такие урлы у вас могут указывать на две разных модели.
Косяк в том, что урлы категорий и подкатегорий таким обраом на первый взгляд неразличимы. Какой это из двух ресурсов, можно понять только из текущего состояния базы, пользователь этого не поймёт по урлу. Это плохо, снижает предсказуемость. Если в базе окажется категория и подкатегория с одинаковыми названиями, одна из них будет недостижима. Упс.
Вариантов решения несколько. Перечислю пришедшие в голову в порядке "разумности".
Сделать урлы разными
Тут всё просто. Я приведу три строчки для маршрутов, а дальше вы догадаетесь, запустив rake routes
resources :categories do resources :subcategories, shallow: true end
Окей, вот примерно как оно будет выглядеть:
/categories/:title /subcategories/:title
Два сегмента, СЕОшники довольны. Правда, на практике пользы от этого будет мало: поисковикам на это наплевать. Но я исхожу из предположения, что "вам никуда от них не деться".
Свести в одну модель
Лучшее по части архтектуры, но на устранение уже нанесённого ей урона надо немного больше времени.
По сути, чем отличаются категория от подкатегории? Категория на верхнем уровне, у неё нет "предка". Если у вас в подкатегории есть category_id, то... Вы смело можете в них же представить и категории, указав им предком nil/NULL. Костыль? Отнюдь, костыль общепринятый, реализован библиотекой acts_as_tree, некогда бывшей частью рельс!
Порядок действий такой:
Бэкап базы! Добавляете колонку parent_id в категории. Копируете всё содержимое таблицы subcategories в categories, записывая значение subcategories.category_id в categories.parent_id Выкидываете модель Subcategory и её таблицу за ненадобностью. Ставите acts_as_tree и пишете его в модель Category, плюс поправляете (убираете) ассоциации. Заменяете Category.all на Category.roots (эквив.: Category.where(parent_id: nil), категории без предка).
По мере роста потребностей вы, возможно, захотите Nested Sets или Closure Tree, но это уже совсем другая история...
Pattern-matching в контроллере или роутах по имени категории
Лютый хак. Заведите в имени какой-нибудь признак, по которому можно понять, искать категорию или подкатегорию. К примеру, ведущий дефис.

Комментариев нет:

Отправить комментарий