【问题标题】:How to keep my gem self-contained without having to edit any core source Rails?如何在无需编辑任何核心源 Rails 的情况下保持我的 gem 独立?
【发布时间】:2014-07-18 18:26:56
【问题描述】:

我想为ApplicationController 添加一个过滤器,但我想在我的 gem 中进行。

我要避免的是:

class ApplicationController < ActionController::Base
  include MyGem
end

我不想那样。我不想在源代码中包含我的模块。

我有问题。

下面是相关代码:

lib/correlation_id/controller_extension

module CorrelationId
  module ControllerExtension

    def self.included(klass)
      klass.class_eval do
        after_filter :pass_correlation_id
      end
    end

    def pass_correlation_id
      correlation_id = request.headers['Correlation-ID'] || SecureRandom.uuid
      headers['Correlation-ID'] = correlation_id
    end
  end
end

ApplicationController.send :include, CorrelationId::ControllerExtension

lib/correlation_id.rb

require 'correlation_id/controller_extension'

module CorrelationId
end

现在,当我在 test/dummy 目录(这是我的 gem 的测试 Rails 应用程序)中时,我尝试使用 rails s 启动服务器并收到以下错误:

/correlation_id/lib/correlation_id/controller_extension.rb:17:in `<top (required)>': uninitialized constant ApplicationController (NameError)

我显然在引用 ApplicationController 来对其进行猴子补丁时遇到问题。

我将如何处理这个问题?我希望我的 gem 是独立的。

【问题讨论】:

  • 所以你想让你的 gem 做一些事情而不把它添加到你的控制器代码中?
  • 它将被添加到控制器代码中。但是,我希望它添加到 gem 中的控制器中,而不是源代码本身中。
  • 我不认为你可以调用你不引用的代码,但我会把这个留给比我更有经验的人。
  • @jkeuhlen 这不是不参考的问题。我将在我的 gem 中引用它。问题是我似乎无法在 gem 中引用它。
  • @RichPeck 我刚刚想通了。将详细回答这个问题。

标签: ruby-on-rails ruby plugins gem


【解决方案1】:

以下代码有效。我所做的是用适当的继承过早地创建ApplicationController。请注意,许多人使用rails-api gem,所以我将它们考虑在内以确保它可以工作。

另外,请注意:您必须从一个类继承,否则ApplicationController 将是一个不了解after_filter 是什么的普通类。

module CorrelationId
  module ControllerExtension

    def self.included(klass)
      klass.class_eval do
        after_filter :pass_correlation_id
      end
    end

    def pass_correlation_id
      correlation_id = request.headers['Correlation-ID'] || SecureRandom.uuid
      headers['Correlation-ID'] = correlation_id
    end

    def self.base_controller_inheritance
      if Gem::Specification.find_all_by_name('rails-api').any?
        ActionController::API
      else
        ActionController::Base
      end
    end
  end
end

class ApplicationController < CorrelationId::ControllerExtension.base_controller_inheritance
  include CorrelationId::ControllerExtension
end

我想可能有更好的方法来检查他们是否使用ActionController::API,如果是,请分享,但到目前为止,这似乎是最可靠的方法。

【讨论】:

    猜你喜欢
    • 2010-12-19
    • 2013-05-24
    • 2019-10-17
    • 1970-01-01
    • 2017-10-17
    • 1970-01-01
    • 2021-11-25
    • 1970-01-01
    • 2013-09-02
    相关资源
    最近更新 更多