如何让我的宝石自成一体,无需编辑任何核心源代码Rails? [英] How to keep my gem self-contained without having to edit any core source Rails?

查看:267
本文介绍了如何让我的宝石自成一体,无需编辑任何核心源代码Rails?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想添加一个过滤器到 ApplicationController ,但我想在我的宝石内完成。



我想避免的是:

  class ApplicationController < ActionController :: Base 
包括MyGem
end

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



我遇到了问题。



以下是相关代码:

lib / correlation_id / controller_extension

 module CorrelationId 
module ControllerExtension

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

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 $ b

  require'correlation_id / controller_extension'

模块CorrelationId
结束

现在,当我进入 test / dummy 目录时,这是我的宝石测试栏应用程序,我尝试使用 rails s 来启动服务器,并且出现以下错误:

  /correlation_id/lib/correlation_id/controller_extension.rb:17:in`< top(required)>':未初始化的常量ApplicationController(NameError)

我很明显在引用ApplicationController的时候遇到了问题,以便对其进行修补。



我如何管理这个?我希望我的宝石自成一体。 下面的代码有效。我所做的是过早地用适当的继承创建 ApplicationController 。请注意,很多人使用 rails-api gem,所以我将它们考虑在内以确保它可以工作。

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

 模块CorrelationId 
模块ControllerExtension

def self.included(klass)
klass.class_eval do
after_filter:pass_correlation_id
end
end
$ b $ def pass_correlation_id
correlation_id = request.headers ['Correlation-ID'] || SecureRandom.uuid
headers ['Correlation-ID'] = correlation_id
end

def self.base_controller_inheritance
如果Gem :: Specification.find_all_by_name('rails-api ')。任何?
ActionController :: API
else
ActionController :: Base
end
end
end
end

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

I想象一下可能有更好的方法来检查它们是否使用 ActionController :: API ,如果是的话,请分享一下,但截至目前,这似乎是最稳定的方式做到这一点。


I want to add a filter to the ApplicationController but I want to do it within my gem.

What I want to avoid is the following:

class ApplicationController < ActionController::Base
  include MyGem
end

I do not want that. I don't want to have to include my module in the source code.

I am having issues though.

Here is the relevant code:

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

Now, when I'm in the test/dummy directory, which is a test rails app for my gem, I try to boot up the server using rails s and I get the following error:

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

I'm clearly having problems with referencing ApplicationController to monkey-patch it.

How would I manage this? I want my gem to be self-contained.

解决方案

The following code works. What I did was prematurely create ApplicationController with the appropriate inheritance. Note, many people use the rails-api gem, so I factored in them to ensure the fact that it would work.

Also, note: You must inherit from a class because otherwise ApplicationController will be a usual class that doesn't understand what after_filter is.

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

I imagine there might be a better way to check if they are using ActionController::API and if so, please do share, but as of now, this seems like the most solid way to do it.

这篇关于如何让我的宝石自成一体,无需编辑任何核心源代码Rails?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆