Reputation: 3024
module X
end
module Y
end
module Z
#TODO include X replacement of including Y
#TODO include Y replacement of including X
end
Is there a way to work around the fact that ruby contains no uninclude keyword??
Upvotes: 11
Views: 4120
Reputation: 717
If you want to make a class that can dynamically choose whether or not to include a module, you can achieve that by including the module on the singleton class during initialization.
That won't get you the same thing as "unincluding" the module on one object's singleton class while keeping included on the class itself (which is what comes to mind for me with uninclude
), but it may match some features of the refinement solution above (that has the same issue) with a different pattern if that sparks some ideas for you.
module A
def hi; :hi; end
end
class Foo
def initialize(include_a = true)
singleton_class.include(A) if include_a
end
end
Foo.new.hi
# => :hi
Foo.new(false).hi
# NoMethodError: undefined method `hi' for #<Foo:0x00007fe19a973f00>
Understand that this is an old question, but if you're looking around for uninclude
functionality, it's worth really thinking about what precisely you're trying to do with it - is something like "dynamic inclusion" enough?
Upvotes: 0
Reputation: 110685
I'm not too happy with this, but it does work if both modules contain the same method names.
file c.rb
module A
def me
puts "I am C"
end
def whosit?
puts "It's me, Becky"
end
end
file d.rb
module A
def me
puts "I am D"
end
end
Then
class X
load('c.rb')
include A
end
x = X.new
x.me # => I am C
x.whosit? # => It's me, Becky
load('d.rb')
x.me # => I am D
x.whosit? # => It's me, Becky !! Unwanted !!
load('c.rb')
x.me # => I am C
load()
is just opening module A and changing and/or adding code; anything there that it does not touch remains. load()
is not real bright. I think it basically does an eval()
and could care less if it loads the same file more than once.
To use this, do not also require
c.rb or d.rb.
Edit: In an earlier edit I added an observation about require_relative
. On reflection, I see it was neither relevant nor interesting, so off with its head.
Upvotes: 0
Reputation: 12578
The genuine answer is that in Ruby, be it 1.x or 2.x, there is no way to uninclude a module once included. But I know that someone, somewhere has written Ruby extension that allows unincluding modules.
EDIT: OK, actually, OP is the duplicate of What is the opposite of Ruby's include?, so according to its answer by @eliah and banister the libraries in question are https://github.com/yrashk/rbmodexcl and https://github.com/banister/mixology19
Upvotes: 1
Reputation: 7399
If you really need this kind of functionality, you could probably do it by using refinements.
class Foo
end
module X
def x
puts 'x'
end
end
module Y
end
module R
refine Foo do
include X
include Y
end
end
# In a separate file or class
using R
# Foo now includes X and Y
Foo.new.x
# In a different file or class
# Foo no longer includes X and Y
Foo.new.x # NoMethodError
Upvotes: 8