2011-11-13 3 views
7

Tôi đang cố sử dụng hai Gems để truy cập Dịch vụ web của Amazon (AWS). Một là Amazon 'aws-sdk', cái kia là 'amazon-ec2'. Tôi đang sử dụng thứ hai như aws-sdk không bao gồm phần đồng hồ điện toán đám mây của các dịch vụ amazon.Tải hai mô-đun Ruby/Gems có cùng tên

Vấn đề là cả hai tải vào cùng một không gian tên.

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) 

Bây giờ điều này dễ hiểu sẽ ném lỗi trên dòng cuối cùng khi mô-đun AWS trỏ vào thư viện bắt buộc đầu tiên, trong trường hợp này là aws-sdk.

NameError: uninitialized constant AWS::Cloudwatch 

Vì vậy, tôi có thể tải một trong số đó vào không gian tên khác không? Một cái gì đó như

require 'aws-sdk', 'AWS_SDK' 
require 'AWS', 'AWS_EC2' 

ec2 = AWS_SDK::EC2.new(config) 
cw = AWS_EC2::Cloudwatch::Base.new(config) 

Hoặc có một mẹo khác tôi có thể sử dụng ở đây?

Cảm ơn

Trả lời

1

Trong Ruby, các mô-đun có cùng tên với các loại đá quý khác nhau không thay thế nhau. Nếu một viên ngọc thực hiện

module AWS 
    class Foo 
    end 
end 

và dụng cụ khác

module AWS 
    class Bar 
    end 
end 

và bạn yêu cầu họ cả hai, bạn sẽ kết thúc với một mô-đun AWS có chứa cả một lớp Foo và một lớp Bar (trừ trường hợp thứ hai làm một cái gì đó thực sự phức tạp như undefining rõ ràng bất cứ điều gì đã có mặt trong các mô-đun, trước khi xác định các công cụ riêng của mình, đó là rất khó). Miễn là đá quý thứ hai không xác định lại bất kỳ phương pháp nào trong đá quý đầu tiên (hoặc cố gắng sử dụng mô-đun dưới dạng lớp hoặc ngược lại), cả hai đều hoạt động tốt. Tôi nghĩ bạn có thể đang tìm kiếm giải pháp sai. Và trong thực tế, điều gì xảy ra cho tôi (trong môi trường chỉ có những viên đá quý này (aws-sdk 1.2.3 và amazon-ec2 0.9.17) và mã chính xác bạn liệt kê ở trên) là chính xác :

.rvm/gems/[email protected]/gems/amazon-ec2-0.9.17/lib/AWS/EC2.rb:2: EC2 is not a module (TypeError) 

Có thể là lỗi bị nuốt phải ở đâu đó và mô-đun AWS :: Cloudwatch chưa được xác định, đơn giản là do khởi tạo đá quý bị hỏng?

+0

Cảm ơn. Có vẻ như có định nghĩa lại lớp/mô-đun xảy ra trong hai thư viện đó. Ví dụ AWS :: EC2 :: Instance là một mô-đun trong amazon-ec2 và một lớp trong aws-sdk. Bất kỳ ý tưởng làm thế nào tôi có thể sử dụng cả hai thư viện này? – Jon

+1

Tôi không nghĩ rằng có thể sử dụng cả hai cùng nhau trong cùng một thông dịch viên Ruby. Có thể bạn không muốn chuyển sang đá quý hỗ trợ Cloudwatch hoặc mang theo mã để thực hiện hỗ trợ Cloudwatch từ một viên đá quý và tích hợp nó với nhau, tôi nghĩ rằng đặt cược tốt nhất của bạn là đặt công cụ Cloudwatch trong một trình thông dịch/quá trình Ruby riêng biệt và gọi nó từ các 'pro' chính của bạn thông qua DRb. Đó là hợp lý đơn giản. Tôi sử dụng kỹ thuật đó trong công việc để giao tiếp giữa một quá trình Ruby và một quá trình JRuby thúc đẩy một số thư viện Java. – Confusion

+0

Hãy nghĩ đó là tuyến đường tôi đang đi xuống. Cảm ơn – Jon

1

Tôi nghĩ rằng tôi đã tìm thấy một giải pháp hoạt động, hãy để tôi minh họa nó bằng một ví dụ. Giả sử chúng ta phải file a.rb và b.rb đó xác định mô-đun cùng với cuộc đụng độ tên thực tế:

#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 

Nếu bạn cần phải yêu cầu cả hai trong số họ, sau đây dường như làm các trick:

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 

Nếu không có sự dup, TMP_A cũng sẽ trỏ đến A quy định tại b.rb sau require_relative, nhưng dup sẽ đảm bảo rằng một bản sao thực được sản xuất thay vì chỉ đơn giản là giữ một tham chiếu đến các module.