【问题标题】:Use two gems in same namespace in Rails在 Rails 的同一个命名空间中使用两个 gem
【发布时间】:2018-08-09 17:44:01
【问题描述】:

我有一个使用 LinkedIn gem 的应用程序,但我需要继续使用 different gem 中的 LinkedIn OAuth2 实现。

我需要在初始 gem 中为现有用户支持对 oAuth1 的请求,但我需要为以后的新用户支持 OAuth2。

问题是,这两个 gem 都使用 LinkedIn 命名空间作为它们的模块名称,并且根据我在 Gemfile 中包含它们的顺序,一个会破坏另一个。

我尝试将 require: false 添加到 gemfile 中,如下所示:

gem 'linkedin', require: false
gem 'linkedin-oauth2', require: false

但奇怪的是,当我进入控制台时,仍然需要第一个,而第二个则不需要:

irb(main):001:0> require 'linkedin'
=> false
irb(main):002:0> require 'linkedin-oauth2'
=> true

这与 require 的工作方式有关吗?是否可以在单独的 lib 文件中仅加载这些 gem 中的一个而不相互破坏?

编辑

我发现我在我的一个规范文件中需要linkedin,这导致它被自动加载,但这仍然不能解决事情被破坏的问题。

当我安装了两个 gem 并运行时:

irb(main):001:0> require 'linkedin'
=> true
irb(main):002:0> ::LinkedIn::Client.new
NameError: uninitialized constant Api::QueryHelpers
        from /Users/me/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/linkedin-1.1.0/lib/linked_in/client.rb:8:in `<class:Client>'
irb(main):004:0> require 'linkedin-oauth2'                                                                                                                                                                                                    
=> true

但如果我从我的 gemfile 中卸载 linkedin-oauth2,它就可以正常工作:

irb(main):002:0> require 'linkedin'
=> true
irb(main):004:0> ::LinkedIn::Client.new
=> #<LinkedIn::Client:0x007f9eef6d72a8 @consumer_token=nil, @consumer_secret=nil, @consumer_options={}>

为什么会这样,特别是因为第一个示例中不需要linkedin-oauth2,但是却发生了错误。可能是因为他们在linkedin gem 中的require supporting files 吗?好像还是不应该影响吧。

【问题讨论】:

  • 您可以移动所有内容以使用 linkedin-oauth2 gem 或自行修改 gem 模块,以便第一个扩展第二个(但不推荐这样做,因为它仍然会破坏名称相同)。
  • “仍然需要第一个” – 你确定你不在其他地方require它吗?
  • @Stefan 是的。我仍然需要它在我的规格之一。所以我解决了这个问题,但现在当我做require 'linkedin' 时,它似乎需要linkedin-oauth2 gem。
  • @Stefan 我编辑了问题并添加了有关我看到的问题的更多详细信息。

标签: ruby-on-rails ruby ruby-on-rails-5


【解决方案1】:

我不建议这样做,因为它可能会产生一些奇怪的副作用,例如如果linkedin-oauth2 使用::LinkedIn 引用自身,但this answer 中显示了重新定义ruby 常量的方法。

我会稍微更改它以防止重命名持续警告...Object.send(:remove_const, :Stripe) 而不是Stripe = Module.new,如答案所示。因此,一个示例(未测试)是:

require 'linkedin-oauth2'
LinkedInOauth2 = LinkedIn

Object.send(:remove_const, :LinkedIn)

require 'linkedin'

【讨论】:

    猜你喜欢
    • 2018-05-25
    • 1970-01-01
    • 1970-01-01
    • 2015-06-15
    • 1970-01-01
    • 2015-09-07
    • 2011-03-15
    • 1970-01-01
    • 2014-08-16
    相关资源
    最近更新 更多