Загрузите два Ruby Modules / Gems с тем же именем - PullRequest
7 голосов
/ 13 ноября 2011

Я пытаюсь использовать два 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 ]

2 голосов
/ 13 ноября 2011

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

module AWS
  class Foo
  end
end

, а другой реализует

module AWS
  class Bar
  end
end

, и вам требуются оба, вы получите модуль AWS, который содержит как класс Foo, так и класс Bar (если второй не делает что-то действительно хитрое, например, явно не определив что-либо уже присутствующее в модуле, прежде чем определять свои собственные вещи, что очень маловероятно).Пока второй драгоценный камень не переопределяет какие-либо методы в первом драгоценном камне (или пытается использовать модуль в качестве класса или наоборот), они оба должны работать нормально.Я думаю, что вы, возможно, ищете неправильное решение.

Редактировать: И на самом деле, что происходит со мной (в среде, где присутствуют только эти драгоценные камни (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 не был определен, просто потому, что инициализациядрагоценный камень идет наперекосяк?

1 голос
/ 19 июня 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...