Загрузите два модуля 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
обеспечит что реальный экземпляр произведен вместо просто держать ссылка на модуль.