ruby-on-rails-3 – 从引擎控制路由加载顺序

前端之家收集整理的这篇文章主要介绍了ruby-on-rails-3 – 从引擎控制路由加载顺序前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
所以在Rails3引擎里有自己的型号/控制器/视图,当然还有路线.现在的问题是:如何确保引擎路线将在之前(或之后)加载应用程序路由和所有其他引擎?

以下是我的Rails应用路线示例:

match '*(path)',:to => 'foo_controller#bar_action'

和我的引擎:

match '/news',:to => 'bar_controller#foo_action'

因此,默认情况下,引擎线路将在应用程序之后加载.这意味着由于我的应用程序中的所有路线,引擎路线无法访问.如何强制引擎路线首先(或最后)加载?

解决方法

你想做什么有点困难.如上所述,引擎路线在应用程序路由之后加载并覆盖此行为可能是有问题的.我可以想到你可以尝试的几件事情.

路由路径初始化器后使用初始化器

在rails源中的engine.rb中有一个初始化器,一个完成你以后的方法是尝试钩住它处理的功能.默认情况下,初始化器看起来像这样:

initializer :add_routing_paths do |app|
  paths.config.routes.to_a.each do |route|
    app.routes_reloader.paths.unshift(route) if File.exists?(route)
  end
end

实际上,这应该是Rails知道的所有路由文件的路径,并尝试将其添加到路由重新加载程序(如果更改则为您自动重新加载路由文件).您可以在此之后定义要执行的另一个初始化程序,然后将检查存储在路由重新加载程序中的路径,拉出属于引擎的路径,将其从路径数组中删除并将其插入,但最后的路径数组.所以在你的config / application.rb中:

class Application < Rails::Application
  initializer :munge_routing_paths,:after => :add_routing_paths do |app|
    engine_routes_path = app.routes_reloader.paths.select{|path| path =~ /<regex that matches path to my engine>/}.first
    app.routes_reloader.paths.delete(engine_routes_path)
    app.routes_reloader.paths << engine_routes_path
  end
end

这可能或可能不起作用,无论哪种方式我都不太乐意推荐它,这并不是特别优雅(就是丑陋的玩恶作剧).

使用Rails 3.1

这可能不是一个选择,但如果是,我可能会去这个.在Rails 3.1中,您可以拥有两种不同类型的引擎,可以完全安装(这里是an SO question talking about some of the differences).但实质上,您将引擎改为可安装的引擎,可安装引擎中的路由是命名空间,您可以将它们明确地包含在主应用程序的路由文件中,例如:

Rails.application.routes.draw do
  mount MyEngine::Engine => "/news"
end

您还可以将您的挂载引擎路线作为范围,并进行各种其他花哨的路线事情(更多信息here).长篇小说,如果可以去3.1,那么这是使用的方法.

从您的引擎动态插入路线到您的主要应用程序

目前最知名的Rails引擎之一是Devise.现在,devise是一个引擎,可能会添加相当多的路由到你的应用程序,但如果你看看设计源码,你会看到它实际上没有一个config / routes.rb文件!这是因为设计动态地将其路由优点添加到您的主应用程序的routes.rb文件中.

当您运行与devise一起使用的模型生成器时,生成器将会做的事情之一是在rails.rb文件的顶部添加一行,如devise_for:model,紧跟在Rails.application.routes.draw之后.因此,在执行生成器以创建用户模型后,您的route.rb与此类似:

Rails.application.routes.draw do
  devise_for :users
  ...
end

现在,devise_for是一个神奇的方法,作为设计的一部分(在lib / devise / rails / routes.rb中),但实质上它将创建一堆基于您生成的模型的常规路由.

我们需要知道的是,设计如何将这条线插入应用程序routes.rb文件中,然后我们可以在引擎中编写一个生成器,它将在主应用程序routes.rb文件的顶部插入任何路由.为此,我们来看看lib / generators / devise / devise_generator.rb.在add_devise_routes方法中,最后一行是路由devise_route. Route是一个Thor动作,将传递给它的字符串插入到主应用的routes.rb文件中.所以我们可以写一个我们自己的生成器,做一些类似的例子:

class MyCrazyGenerator < Rails::Generators::NamedBase
  ...
  def add_my_crazy_routes
    my_route  = "match '/news',:to => 'bar_controller#foo_action'"
    route my_route
  end
end

当然,你需要确保所有的发电机基础设施都已经到位,但这是它的本质. Devise是由一些非常聪明的导轨,由很多人使用,模仿他们做的可能是一个很好的方式去.在我建议的3件事情中,我会处理你的问题(考虑到移动到rails 3.1可能不是一个选择).

原文链接:https://www.f2er.com/ruby/273693.html

猜你在找的Ruby相关文章