2

我有一个引擎(由我/我工作的公司开发),我们在几个不同的项目中使用它。我刚刚将它转换为使用带有资产管道的 rails 3.1 并且一切似乎都在工作......在大多数情况下。

我的问题是我需要UsersController使用一些特定于应用程序的香料来扩展 的功能,但我不确定最好的方法。引擎没有定义Users#show动作,但是这个应用确实需要它,所以我在路由文件中添加了:

JobEngine::Application.routes.draw do
  root :to => 'home#index'

  resource :users, :only => [:show]
  resources :jobs, :only => [:show]
end

然后在我的应用程序中创建了 UsersController:

class UsersController < MyEngine::UsersController
  def show
  end
end

然后我做了一个users/show.html.haml视图,我把它剥离了,只显示一个问题行:

= link_to "Somewhere", job_path(3)

这给了我一个错误,上面写着undefined method 'job_path' for #<#<Class:0x00000102d69900>:0x00000102d4ed30>

这很奇怪,因为我让我的应用程序UsersController继承MyEngine::UsersController它之前工作得很好。

当我rake routes在控制台中进行操作时,有以下几行:

users GET   /users(.:format)    {:action=>"show", :controller=>"users"}
job GET     /jobs/:id(.:format) {:action=>"show", :controller=>"jobs"}

我可以将类定义更改为:

class UsersController < ApplicationController

然后链接工作得很好。但是,引擎的控制器MyEngine::UsersController已经继承自ApplicationController. 我可以将代码放入我的应用程序ApplicationController(如 a before_filter),它会按预期运行,所以我知道我的类定义最终会影响我的应用程序ApplicationController,为什么 job_path 助手不起作用?

当我将显示操作更改为:

def show
  job_path(3)
end

我得到错误:

ActionController::RoutingError (No route matches {:action=>"show", :controller=>"jobs", :id=>3}):
app/controllers/users_controller.rb:9:in `show'

这进一步让我感到困惑,因为现在它实际上确实将 job_path 识别为一种方法,但不知何故,路由器没有使用所有正确的参数选择去哪里。

我究竟做错了什么?扩展引擎控制器功能的正确方法是什么?我在这里看到了扩展引擎功能问题。

并遵循该代码示例,将我的类定义更改为重新打开MyEngine::UsersController,但我仍然得到完全相同的结果job_path(NUMBER)

更新:

好的,我有点弄清楚发生了什么。假设您的引擎有一个 job_path 路由,而您的应用程序有一个 job_path 路由。如果您在通过引擎控制器访问的页面上,您可以使用 调用引擎的助手job_path,但您也可以使用 调用主应用程序的助手main_app.job_path

同样,如果您在通过应用程序控制器之一访问的页面上,您可以my_engine.job_path使用job_path. 这是假设你有类似的东西mount MyEngine::Engine => "/my_engine", :as => 'my_engine'

当您从应用程序继承引擎控制器时,它会完全改变您的路由助手,使其认为您在控制器/视图生命周期中处于引擎的上下文中。所以要解决我的问题,我真正需要做的就是改变它main_app.job_path(3)并且它可以工作。

我对这个解决方案并不完全满意,因为它感觉有点……奇怪。也许我在这个页面上有一个部分,将在一个单独的非继承页面上使用。现在链接助手将只适用于两个页面之一,但永远不会两个=\我在这里遗漏了什么......?

4

2 回答 2

1

尝试在主应用程序的路线中更改您的安装路径,如下所示,

mount MyEngine::Engine => "/"

这将解决您的问题。

于 2011-12-27T07:46:04.410 回答
0

尽管您可以使这种方法发挥作用,但语义不会创建干净的体系结构。您可以从控制器的复制中推测出这一点Users——这意味着某些User功能在 AppEngine 中处理,而某些功能在父应用程序本身中处理。

相反,请考虑应用程序中唯一存在的功能,以及打包到 AppEngine gem 中的功能。也许使用JobEngine,正如您所说的那样,您的Users控制器实际上有一个,并且在应用程序中,控制器有处理 CRUD、配置文件、消息队列等UsersStatisticsController的“真正的通用” 。UsersController

如果您觉得必须将它们统一到一个控制器中(而不是给它们不同的命名法),那么您最好创建一个命名空间控制器,从而可以将各种功能结合起来。

尽管这增加了复杂性,但通常可以说这是最合理的解决方案。 这是关于它的另一篇文章

于 2011-12-27T18:20:58.613 回答