Загрузите два модуля Ruby / Gems с одинаковым именем

Я пытаюсь использовать два драгоценных камня для доступа к Amazon Web Services (AWS). Один из них-Amazon aws-sdk, другой-amazon-ec2. Я использую второй, поскольку aws-sdk не охватывает раздел cloudwatch сервисов amazon.

проблема в том, что оба загружаются в одно и то же пространство имен.

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) 

или есть еще один трюк, который я мог бы использовать здесь?

спасибо

2 ответов


в Ruby модули с одинаковым именем из разных драгоценных камней не заменяют друг друга. Если один драгоценный камень реализует

module AWS
  class Foo
  end
end

и другие орудия

module AWS
  class Bar
  end
end

и вы требуете их обоих, вы получите модуль AWS, который содержит как класс Foo, так и панель классов (если только второй не делает что-то действительно сложное, например, явно не определяя ничего, уже присутствующего в модуле, прежде чем определить свой собственный материал, что очень маловероятно). Пока второй камень не изменить любые методы в первом 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 не был определен просто потому, что инициализация драгоценного камня идет наперекосяк?


Я думаю, что нашел решение, которое работает, позвольте мне проиллюстрировать его примером. Предположим, мы должны подать 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 также будет указывать A определено в b.rb после require_relative, а dup обеспечит что реальный экземпляр произведен вместо просто держать ссылка на модуль.