Вложенные ресурсы - Как избежать избыточных маршрутов? - PullRequest
4 голосов
/ 29 января 2011

У меня есть это дерево ресурсов:

  • Форум
    • Тема
      • Сообщение

Я хочу иметь возможность получать к ним доступ независимо, когда это возможно. Я хочу избежать избыточных маршрутов, таких как /forum/:forum_id/topic/:topic_id/post/:id, потому что я могу просто сделать /post/:id.

Идеальные маршруты выглядят так:

/forums => Forums#index              # Lists every forum
/forum/new => Forums#new             # New forum
/forum/edit => Forums#edit           # Edit forum
/forum/:id  => Forums#show           # Shows forum
/forum/:id/forums Forums#index       # Lists nested forums
/forum/:id/topics => Topics#index    # Lists topics inside forum
/forum/:id/topic/new => Topics#new   # New topic
/topics => Topics#index              # Lists every topic
/topic/:id => Topics#show            # Shows topic
/topic/:id/posts => Posts#index      # Lists posts inside topic
/topic/:id/post/new => Posts#new     # New post
/posts => Posts#index                # Lists every post
/post/:id => Posts#show              # Shows post

Как лучше всего смоделировать эту ситуацию?

Вот что я попробовал:

resources :forums
resources :topics
resources :posts

resources :forums do
  resources :topics
end

resources :topics do
  resources :posts
end

Проблема в том, что эти настройки создают множество бесполезных маршрутов, например:

/forums/:forum_id/topic/:id # Redundant - /topic/:id
/topics/:topic_id/post/:id  # Redundant - /post/:id
/topics/new                 # No current forum
/posts/new                  # No current topic

Есть ли способ указать, какие маршруты создавать?

Как в контроллерах обрабатывать несколько маршрутов, привязанных к одному действию? Например, внутри Topics#index как узнать, должен ли я обрабатывать GET /forum/:id/topics или GET /topics?

Ответы [ 2 ]

2 голосов
/ 29 января 2011

Вложенные маршруты нужны только для действий index, когда родительский объект обнаружил коллекцию ресурсов.В противном случае речь идет о SEO.Большинство пользователей не заметят, как генерируются их URL, и не заботятся о них, поэтому все дело в поисковых системах.Я вижу, куда вы идете, но будет больше работы, чтобы не генерировать маршруты, так как соглашение в этом примере перечисляет ресурс с одной строкой кода.И, конечно, вы уже знаете это, но это только мой взгляд на вещи.

a) forms_path #if you want to find all forms
b) topics_path #if you want to find all topics #possible use, maybe in a tag listing.
c) posts_path #if you want to find all posts #probably never use

Вы, вероятно, никогда не захотите найти все темы и особенно сообщения, но это будут способы использования.

d) form_topics_path(form) #find all topics of a given form 
e) form_topic_path(form, topic)  #only find one topic on a give form
f) topic_path #find a given topic

В последних двух, e и f, форма не нужна, так как вы знаете, какую тему вы хотите.Если вы беспокоитесь о SEO и хотите, чтобы ваши URL были хорошими для поисковых систем, то, вероятно, захотите использовать e.

g) form_topic_posts_path(form, topic) #I'm already confused 
h) form_topic_post_path(form, topic, post) #still to deep
i) topic_posts_path(topic) #most rails people think two levels is deep enough
j) topic_post_path(topic, post) #might be good for seo

Это действительно вопрос SEO и сохранения ваших URL дружественными, кроме вложенного ресурса, которому нужен их родительский идентификатор.чтобы найти соответствующие сообщения, такие как пропуск form для поиска связанных тем и пропуск topic для поиска соответствующих сообщений.

Если вы используете topic_path, topics_path post_path,post_path вы упускаете из виду лучшие URL, но с точки зрения лучшего URL для двигателей, которые читаются, но они действительно не нужны.

С точки зрения не генерации маршрутов, на самом деле спрос на это не существуетпотому что это усложнит задачу, чем просто объявить ресурс в одной строке, где конечная цель - просто ведение домашнего хозяйства.

1 голос
/ 29 января 2011

Я решил свою проблему, ограничив маршруты, которые генерирует каждое объявление ресурса:

resources :forums do
  resources :topics, only: [ :index, :new, :create ]
end

scope except: [ :new, :create ] do
  resources :posts
  resources :topics do
    resources :posts, only: [ :index, :new, :create ]
  end  
end

Что касается проблемы с контроллером, я просто проверяю, было ли передано id:

# Topics#index
if forum_id = params[:forum_id]
  @topics = Forum.find(forum_id).topics.paginate page: params[:page]
else
  @topics = Topic.paginate page: params[:page]
end
...