Динамические маршруты с Rails 3 - PullRequest
13 голосов
/ 16 ноября 2010

У меня есть задача разработать приложение rails, следуя модели маршрутизации.

Мне нужна модель PageController и Page.URL страницы должны быть похожи на /contacts, /shipping, /some_page.

Также мне нужна модель CatalogController и Category.URL-адреса категорий должны быть такими, как /laptops, /smartphones/android.

И это будет ProductsController и Product модель, URL-адреса товаров должны быть линейными /laptops/toshiba_sattelite_l605, /smartphones/android/htc_magic

Я понимаюЭта проблема может быть решена с помощью URL-адресов, таких как

  • /page/shipping
  • /catalog/smartphones/android

Но клиент не хочет видеть вставку«/page» или «/catalog» в URL.

Скажите, пожалуйста, как решить эту проблему.Извините за мой плохой английский.

Ответы [ 5 ]

49 голосов
/ 19 ноября 2010

Вам нужно будет написать правило "catch-all":

На маршрутах.rb:

get '*my_precioussss' => 'sauron#one_action_to_rule_them_all'

Ваш драгоценный контроллер:

class SauronController < ApplicationController
  def one_action_to_rule_them_all
    @element = find_by_slug(params[:my_precioussss])
    render @element.kind # product, category, etc
  end
end

Затем вы пишете одно представление для каждого «вида» элемента: product.html.erb, category.html.erb и т. Д.

Убедитесь, что вы пишете свою реализацию find_by_slug.

Вы можете изменить one_action_to_rule_them_all на pikachu_i_choose_you и SauronController на PokemonController, тоже будет работать.

4 голосов
/ 08 июля 2011

Вам нужно написать перехват всех

match '*page' => 'pages#show'

, а затем обработать путь к странице в вашем контроллере страниц

def show
  if params[:page] 
    @page = Page.find_by_page(params[:page])
  else
    @page = Page.find(params[:id])
  end
...

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

match '*page' => 'pages#show', :constraints => lambda{|req|  !req.env["REQUEST_URI"].include? "auth"}

Если вы хотите иметь вложенные пути (например, «смартфоны / андроид»), вам нужно разделить страницу:парам друг от друга и обрабатывать сегменты пути в вашем контроллере

path = :page.split("/")  // you now have an array of path segments you can use in your controller
1 голос
/ 09 апреля 2012

я сделал это в сочетании двух подходов

  1. использовать гем friendly_id для работы со слагами в запросах на поиск вместо числовых идентификаторов

  2. определяет маршруты с :constraints=>ConditionClass, который должен возвращать true или false (поэтому маршрут будет определен или нет)

маленький пример:

#routes.rb
    class CategoryBrandGoodConstraint
      def self.matches?(request)
        path_parts = request.path.split('/')
        Category.find(path_parts[1]).present?&&Brand.find(path_parts[2]).present?&&Good.find(path_parts[3]).present? rescue false
      end
    end

    get ':category_friendly_id/:brand_friendly_id/:good_friendly_id' => 'goods#index', :constraints => CategoryBrandGoodConstraint
    #another conditional routes with another :constraints=>ConditionClass2 definition
    #...
    #until you define all necessary conditional application routes

#goods_controller.rb

    def index

      #operate with params[:category_friendly_id], params[:brand_friendly_id], params[:good_friendly_id] to collect all you need for view rendering

    end

конечно, вы можете направить на другой контроллер для рендеринга другого представления get '/:whatever' => 'another_controller#another_action', :constraints=>ConditionClassN

надеюсь, это поможет!

ура

1 голос
/ 24 ноября 2011

Я нашел это руководство по прокладке рельсов 3 невероятно полезным:

http://www.engineyard.com/blog/2010/the-lowdown-on-routes-in-rails-3/

0 голосов
/ 16 ноября 2010

Маршруты Rails основаны исключительно на URL. Если у вас нет /pages или /categories или чего-либо еще перед именем, то как Rails скажет, является ли URL, такой как http://example.com/smartphones, URL-адресом страницы или категории? Если у вас нет предварительно определенного списка имен страниц в условиях маршрутов, он не может.

Единственный способ сделать это в этом примере - это выполнить поиск страницы по smartphones и, если ничего не найдено, предположить, что это имя категории, и выполнить поиск категории. Это не может быть сделано на маршрутах рельсов. Для этого вам понадобится один контроллер, который будет обрабатывать все эти URL-адреса, выполнять поиск и затем отображать правильный шаблон (вы не сможете перенаправить, потому что это изменит URL-адрес). И это ужасный способ решить эту проблему.

На вашем месте я бы попытался убедить клиента согласиться с каким-то префиксом (например, /p_pagename) или, желательно, с другими URL-адресами. Это может быть что-то вроде /p/shipping для страниц, а все другие URL-адреса могут быть направлены на CategoriesController или ProductsController.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...