I'm writing a small Ruby command-line application that uses fileutils
from the standard library for file operations. Depending on how the user invokes the application, I will want to include either FileUtils
, FileUtils::DryRun
or FileUtils::Verbose
.
Since include
is private, though, I can't put the logic to choose into the object's initialize
method. (That was my first thought, since then I could just pass the information about the user's choice as a parameter to new
.) I've come up with two options that seem to work, but I'm not happy with either:
Set a global variable in the app's namespace based on the user's choice, and then do a conditional include in the class:
class Worker
case App::OPTION
when "dry-run"
include FileUtils::DryRun
etc.
Create sub-classes, where the only difference is which version of FileUtils
they include. Choose the appropriate one, depending on the user's choice.
class Worker
include FileUtils
# shared Worker methods go here
end
class Worker::DryRun < Worker
include FileUtils::DryRun
end
class Worker::Verbose < Worker
include FileUtils::Verbose
end
The first method seems DRY-er, but I'm hoping that there's something more straightforward that I haven't thought of.
Conditionally including the module through the send methods works for me as in the below tested example:
class Artefact
include HPALMGenericApi
# the initializer just sets the server name we will be using ans also the 'transport' method : Rest or OTA (set in the opt parameter)
def initialize server, opt = {}
# conditionally include the Rest or OTA module
self.class.send(:include, HPALMApiRest) if (opt.empty? || (opt && opt[:using] opt[:using] == :Rest))
self.class.send(:include, HPALMApiOTA) if (opt && opt[:using] opt[:using] == :OTA)
# ... rest of initialization code
end
end
So what if it's private?
class Worker
def initialize(verbose=false)
if verbose
(class <<self; include FileUtils::Verbose; end)
else
(class <<self; include FileUtils; end)
end
touch "test"
end
end
This includes FileUtils::something
in particular's Worker
's metaclass - not in the main Worker
class. Different workers can use different FileUtils
this way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With