在覆盖Rails引擎视图/布局时访问主应用程序助手

时间:2012-02-10 17:35:38

标签: ruby-on-rails ruby-on-rails-3.1 rails-engines rails-3.1

我创建了一个简单的Rails引擎,为应用程序提供了一些通用功能(照片库)。我希望能够覆盖标准_header部分,以便库的菜单与我的主应用程序的菜单匹配。在我的标题视图中,我调用了一个帮助程序,它是application_helpers(主应用程序)的一部分,但我不断收到“未定义的方法”错误。据我所知,当我覆盖引擎应用程序布局或其部分时,主应用程序application_helpers没有被包括(显然)。

所以我的问题是,如何覆盖主应用程序中的引擎视图,并获得对主应用程序帮助器方法的访问权限?我仍然需要访问引擎帮助程序,而不是搞砸引擎功能。

我是否还需要覆盖控制器?得到一些帮助似乎很多。

由于

Rails 3.1.3

5 个答案:

答案 0 :(得分:3)

查看此博文:http://www.candland.net/2012/04/17/rails-routes-used-in-an-isolated-engine/ 作者将一个method_missing定义添加到应用程序助手中,以便访问父应用程序的助手。

/config/initializers/blogit.rb

module Blogit
    module ApplicationHelper
      def method_missing method, *args, &block
        puts "LOOKING FOR ROUTES #{method}"
        if method.to_s.end_with?('_path') or method.to_s.end_with?('_url')
          if main_app.respond_to?(method)
            main_app.send(method, *args)
          else
            super
          end
        else
          super
        end
      end

      def respond_to?(method)
        if method.to_s.end_with?('_path') or method.to_s.end_with?('_url')
          if main_app.respond_to?(method)
            true
          else
            super
          end
        else
          super
        end
      end
    end
  end

答案 1 :(得分:2)

尝试包含主要的app帮助程序方法。例如:

class MyEngineClass
  include ApplicationHelper

  #...
end

您可能需要先请求该文件,但我希望Rails能够在这种情况下正确找到它。

包含ApplicationHelper后,您应该可以直接在控制器中使用这些帮助程序。

看起来你可以为很多Rails类调用ClassName.helper("application") - 不确定这是否适用于此。

答案 2 :(得分:1)

尝试在您的应用程序中创建一个帮助程序,并在引擎中使用相同的帮助程序名称来覆盖引擎辅助程序方法。

我发现this discussion特别有见地。在{em>隔离引擎帮助下的Rails Engine API docs中也有一些有趣的想法。

答案 3 :(得分:1)

引擎应该独立于主应用程序,这就是您无法从引擎访问其帮助程序的原因。

但是,有一些黑客方法可以让您的引擎访问主应用程序的帮助程序。我就这样做了:

# In the main app
# initializers/share_helpers_path_with_engine.rb
PhotoGallery::Engine.class_eval do
  paths["app/helpers"] << File.join(File.dirname(__FILE__), '../..', 'app/helpers')
end

您当然需要将PhotoGallery更改为引擎类的实际名称。

请随意查看引擎文档(有关路径的部分):http://edgeapi.rubyonrails.org/classes/Rails/Engine.html

答案 4 :(得分:0)

免责声明:我只在Rails 3.2引擎中使用此解决方案。

如果您的引擎中有标准标题部分 vendor / gems / my_gallery_engine / app / views / application / _header.html.erb

然后,通过创建自定义的部分 app / views / application / _header.html.erb ,在主应用中覆盖它。

覆盖有效,因为Rails的视图模板搜索路径(默认情况下)以主应用的 app / views 目录开头,然后搜索引擎的 app / views 按加载顺序。

所有主要应用程序的助手都将在部分内容中使用。