Load two Ruby Modules/Gems with the same name
In Ruby, modules with the same name from different gems don't replace each other. If one gem implements
module AWS
class Foo
end
end
and another implements
module AWS
class Bar
end
end
and you require them both, you will end up with an AWS module that contains both a class Foo and a class Bar (unless the second does something really tricky like explicitly undefining anything already present in the module, before defining its own stuff, which is very unlikely). As long as the second gem doesn't redefine any methods in the first gem (or attempts to use a module as a class or vice versa), they should both work fine. I think you may be looking for the wrong solution.
Edit:
And in fact, what happens for me (in an environment with only these gems present (aws-sdk 1.2.3 and amazon-ec2 0.9.17) and the exact code you listed above) is exactly that:
.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)
Could it be that an error gets swallowed somewhere and that the module AWS::Cloudwatch hasn't been defined, simply because the initialization of the gem goes awry?
Two Ruby gems using the same namespace
This seems like a perfectly acceptable way to structure your gems. In your code sample, Foo::Bar
and Foo::Baz
will be two completely different classes within the same namespace, and they will not clash with each other. This is true even if you used the same method names within the two classes:
module Foo
class Bar
def do_thing
puts "Bar!"
end
end
end
module Foo
class Baz
def do_thing
puts "Baz!"
end
end
end
In this modified example, Foo::Bar#do_thing
will output "Bar!"
and Foo::Baz#do_thing
will output "Baz!"
, since they are separate methods in separate classes. This approach allows you to swap out Foo::Baz
objects for Foo::Bar
objects to change behavior, since they have the same interface.
If you wanted your third-party API gem to extend the functionality of your vanilla API gem, you may want to consider adjusting your approach to use inheritance.
Ruby Rails: How Rails handle same method name in in two different gems
To answer your question directly: This is ultimately the responsibility of the developer who uses the gems. The authors of gems should take some care to name their methods appropriately, but nothing they can (or should) do will obviate the possibility of a collision.
This feature of Ruby is very powerful, but as always, with great power comes great potential for disaster.
how to require different gems with the same name?
As others answers and comments have said, you cannot simply require both gems as they are.
However, given that both are hosted on GitHub, you could fork one of them and rename the offending classes. So long as your renaming is consistent within the gem you could use your fork within your Gemfile
Of course, you wouldn't be easily able to rebase changes onto your fork easily but if you really must use both gems this might be a compromise that you are happy with.
How to have multiple gems that share the same common Ruby module?
Summarizing comments above for posterity...
There are a couple things to consider here.
1. Is commonCode
significant? Is it a good chunk of code, or just a few files?
2. Are gemA
and gemB
significant? Should each of them really be gems?
Seems like you're in either one of two situations, depending on the significance of the code you've written:
commonCode
is significant enough (amount of code, complexity, logical separation fromgemA
andgemB
) to merit its own gem? If so, definitely pull it out into its own gem. You can requiregem-common
in the other two. It doesn't make sense to require a plain ruby file inA
andB
that lives outside of those two code bases.commonCode
is too insignificant to be pulled into its own gem. If this is the case, you should consider whether or notgemA
andgemB
really deserve their own gems, each. If they aren't big enough or logically separate enough, maybe all three can be combined into a larger gem.
Use two gems in same namespace in Rails
I wouldn't recommend doing this, since it could have some weird side effects such as if linkedin-oauth2 references itself with ::LinkedIn
, but a method to redefine a ruby constant is shown in this answer.
I would change it a little bit to prevent renaming a constant warning... Object.send(:remove_const, :Stripe)
instead of the Stripe = Module.new
as shown in the answer. So, an example (not tested) would be:
require 'linkedin-oauth2'
LinkedInOauth2 = LinkedIn
Object.send(:remove_const, :LinkedIn)
require 'linkedin'
Related Topics
Convert a String of 0-F into a Byte Array in Ruby
How to Inspect What Is the Default Value for Optional Parameter in Ruby's Method
Convert Hash Keys to Lowercase -- Ruby Beginner
Rails Shows "Warning: Can't Verify Csrf Token Authenticity" from a Restkit Post
Is the .Each Iterator in Ruby Guaranteed to Give the Same Order on the Same Elements Every Time
Unable to Install MySQL2 Gem on Bigsur
Ruby Equivalent of PHP's ".=" (Dot Equals) Operator
How to List the Available Variables in an Ruby Erb Template
What Is the Purpose of 'Kernel'
How to Change the Default Value of a Struct Attribute
Why Don't More Projects Use Ruby Symbols Instead of Strings
Using Phonegap as a Native Container for a Rails 3 App
Use Ruby Array for a JavaScript Array in Erb. Escaping Quotes