加载两个名称相同的Ruby Modules / Gems
我正在尝试使用两个Gems来访问Amazon Web Services(AWS)。 一个是亚马逊’aws-sdk’,另一个是’amazon-ec2’。 我正在使用第二个,因为aws-sdk没有涵盖亚马逊服务的cloudwatch部分。
问题是两者都加载到同一名称空间。
require 'aws-sdk' # aws-sdk gem require 'AWS' # amazon-ec2 gem config = {:access_key_id => 'abc', :secret_key => 'xyz'} # start using the API with aws-sdk ec2 = AWS::EC2.new(config) # start using the API for anazon-ec2 cw = AWS::Cloudwatch::Base.new(config)
现在,这可以理解地在最后一行引发错误,因为AWS模块指向第一个必需的库,在本例中为aws-sdk。
NameError: uninitialized constant AWS::Cloudwatch
那么,我可以将其中一个加载到另一个名称空间中吗? 就像是
require 'aws-sdk', 'AWS_SDK' require 'AWS', 'AWS_EC2' ec2 = AWS_SDK::EC2.new(config) cw = AWS_EC2::Cloudwatch::Base.new(config)
或者我可以在这里使用另一种技巧吗?
谢谢
在Ruby中,来自不同gem的同名模块不会互相替换。 如果一个gem实现
module AWS class Foo end end
和另一个工具
module AWS class Bar end end
并且你需要它们两个,你将得到一个包含类Foo和类Bar的AWS模块(除非第二个做了一些非常棘手的事情,比如在定义自己的东西之前明确地取消定义模块中已有的东西,这是非常不可能)。 只要第二个gem没有重新定义第一个gem中的任何方法(或者尝试将模块用作类,反之亦然),它们都应该正常工作。 我想你可能在寻找错误的解决方案。
编辑:事实上,对我来说会发生什么(在只有这些gem存在的环境中(aws-sdk 1.2.3和amazon-ec2 0.9.17)以及上面列出的确切代码)正是如此:
.rvm/gems/ree-1.8.7-2011.03@ec2/gems/amazon-ec2-0.9.17/lib/AWS/EC2.rb:2: EC2 is not a module (TypeError)
可能是因为错误被某个地方吞没而且模块AWS :: Cloudwatch尚未被定义,仅仅是因为gem的初始化出错了?
我想我找到了一个有效的解决方案,让我用一个例子来说明。 假设我们必须使用文件a.rb和b.rb来定义具有实际名称冲突的相同模块:
#file a.rb module A def self.greet puts 'A' end end #file b.rb module A def self.greet puts 'other A' end end
如果您需要同时使用它们,以下似乎可以解决问题:
require_relative 'a' TMP_A = A.dup A.greet # => A TMP_A.greet # => A require_relative 'b' TMP_A2 = A A.greet # => other A TMP_A2.greet # => other A TMP_A.greet # => A
如果没有dup
, TMP_A
也将指向require_relative
之后b.rb中定义的A
,但dup
将确保生成真实副本而不是简单地保存对模块的引用。
- 在AWS EC2上安装Ruby 2.0和Rails 4.0.0beta
- 与ror托管错误
- AWS Rails安装失败:activesupport需要Ruby版本> = 2.2.2
- Rubber和Amazon EC2托管问题(Net :: SSH :: AuthenticationFailed:root)
- cap使用admin而不是ec2-user
- ruby:没有这样的文件加载 – 运行cap rubber时的ubygems(LoadError):create_staging
- 在ssh终止后如何使服务器在EC2上运行
- MySQL不会在与Rubber部署的EC2上连接
- 对于AWS,如何使用ruby aws-sdk将标记设置为资源?