контроллер переключателей - PullRequest
0 голосов
/ 30 июля 2009

Мне нужно разделить модели: вложенные разделы и статьи, раздел has_many статей. Оба имеют атрибут пути, такой как aaa / bbb / ccc, например:

movies # section
movies/popular # section
movies/popular/matrix # article
movies/popular/matrix-reloaded # article
...
movies/ratings # article
about # article
...

В маршрутах у меня есть:

map.path '*path', :controller => 'path', :action => 'show'

Как создать действие шоу, например

def show
  if section = Section.find_by_path!(params[:path])
    # run SectionsController, :show
  elsif article = Article.find_by_path!(params[:path])
    # run ArticlesController, :show
  else
    raise ActiveRecord::RecordNotFound.new(:)
  end
end

Ответы [ 2 ]

1 голос
/ 31 июля 2009

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

map.resources :section
map.resources :articles

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

Обновление

Вот простое пошаговое руководство по добавлению такого рода функциональности с использованием Rails Metal компонента и предоставленного вами кода. Я предлагаю вам взглянуть на упрощение поиска сегментов пути, поскольку вы дублируете большую часть работы с базой данных с текущим кодом.

$ script/generate metal path_rewriter
      create  app/metal
      create  app/metal/path_rewriter.rb

path_rewriter.rb

# Allow the metal piece to run in isolation
require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails)

class PathRewriter
  def self.call(env)
    path = env["PATH_INFO"]
    new_path = path

    if article = Article.find_by_path(path)
      new_path = "/articles/#{article.id}"

    elsif section = Section.find_by_path(path)
      new_path = "/sections/#{section.id}"

    end

    env["REQUEST_PATH"] = 
    env["REQUEST_URI"]  = 
    env["PATH_INFO"]    = new_path

    [404, {"Content-Type" => "text/html"}, [ ]]
  end
end

Для хорошего знакомства с Metal и Rack в целом, посмотрите эпизод Ryan Bates 'Railscast на Metal и эпизод на Rack .

1 голос
/ 30 июля 2009

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

def show
  if @section = Section.find_by_path!(params[:path])
    render :template => 'section/show'
  elsif @article = Article.find_by_path!(params[:path])
    render :template => 'article/show'
  else
    # raise exception
  end
end

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

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