When developing your own Ruby gem, at some point you might need to make some of the parameters configurable. The most idiomatic and elegant way to achieve this in Ruby is global configuration using a block. In my opinion, this approach is so simple that you likely won’t need any third-party gems for it. However, there are a few important caveats to keep in mind:
- Avoid referencing your config directly inside methods. Instead, use the configuration to set a default value for your method’s parameter (see the example image). Alternatively, add an optional config parameter to the method - this allows caller code to override the global configuration for a specific invocation.
- This pattern is not thread-safe. You should apply your configuration at boot time, before spawning any threads (this is especially crucial if your configuration class performs any side effects).
How do you implement configuration in your own gems? What aspects should be considered?
module MyLib
class Config
attr_accessor :some_setting
def initialize
@some_setting = 'default value'
end
end
def config
@config ||= Config.new
end
def configure(&block)
block&.call(config)
end
def process(value = config.some_setting)
puts "Processing with #{value.inspect}"
end
module_function :config, :configure, :process
end
MyLib.configure do |c|
c.some_setting = 'other value'
end
MyLib.process # Processing with "other value"