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可能不是一个选择). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |