Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 转换轨控制器_Ruby On Rails - Fatal编程技术网

Ruby on rails 转换轨控制器

Ruby on rails 转换轨控制器,ruby-on-rails,Ruby On Rails,我必须分开模型:嵌套的部分和文章,部分有很多文章。 两者都具有类似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', :con

我必须分开模型:嵌套的部分和文章,部分有很多文章。 两者都具有类似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

与其实例化其他控制器,我只需根据路径是否与节或文章匹配,呈现不同于PathController的show操作的模板。i、 e

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

原因是,虽然您可以在另一个控制器中创建一个控制器的实例,但它不会按您希望的方式工作。i、 e.第二个控制器将无权访问您的参数、会话等,然后调用控制器将无权访问实例变量和在第二个控制器中发出的呈现请求。

您应该使用机架中间件拦截请求,然后为适当的Rails应用程序重写url。这样,您的路由文件仍然非常简单

map.resources :section
map.resources :articles
在中间件中,您查找与路径关联的实体,并将url重新映射到简单的内部url,从而允许Rails路由分派到正确的控制器,并正常调用过滤器链

更新

下面是使用组件和您提供的代码添加此类功能的简单演练。我建议您考虑简化如何查找路径段,因为您正在用当前代码复制大量数据库工作

$ script/generate metal path_rewriter
      create  app/metal
      create  app/metal/path_rewriter.rb
path\u 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

要了解金属和机架的一般使用方法,请查看Ryan Bates的Railscast和。

但我必须复制这些控制器中的所有过滤器,并显示所有操作您有哪些过滤器?也许可以将它们移动到公共超类或mixin,因为您可能希望它们应用于PathController以及SectionController和ArticleController。您是否曾经通过SectionController和ArticleController显示一个节或活动,或者所有显示请求现在都通过PathController路由?目前-访问限制(文章或节是否公开),但项目正在开发中,因此在不久的将来可能会出现某些内容我应该在路由模块之前拦截?或者有没有办法用proc/lambda创建路由?是的,在路由模块之前拦截。然后,“Rails”应用程序中的路由保持正常,但中间件应用程序会根据浏览器报告的路径重写传入的URL。