Created
December 28, 2010 15:38
-
-
Save s-andringa/757335 to your computer and use it in GitHub Desktop.
Deal with bitmask-form options & Safely monkey patch Ruby gems
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ConstantGardener | |
def self.create(*booleans) | |
Class.new do | |
def initialize(bitmask) | |
@bitmask = bitmask | |
end | |
booleans.each_with_index do |b, i| | |
const_set b.to_s.upcase, 2**i | |
define_method "#{b.to_s.downcase}?" do | |
@bitmask[i] == 1 | |
end | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rubygems' | |
require 'constant_gardener' | |
module GemPatch | |
Strategy = ConstantGardener.create(:warn, :skip, :raise) | |
class << self | |
private | |
def versions_to_sentence(versions) | |
if versions.size == 1 | |
"version #{versions.first}" | |
else | |
"versions " + versions[0..-2].join(', ') + " and " + versions.last.to_s | |
end | |
end | |
end | |
end | |
class GemPatchError < StandardError; end | |
module Kernel | |
def patch(gem_spec, strategy = GemPatch::Strategy::RAISE, &block) | |
name, *versions = gem_spec.split(/\s+/) | |
wanted_versions = versions.map{ |v| Gem::Version.new(v) } | |
loaded_version = Gem.loaded_specs[name] ? Gem.loaded_specs[name].version : nil | |
strategy = GemPatch::Strategy.new(strategy) | |
error = if !loaded_version | |
"You patched #{name} in #{caller.first} but #{name} was not loaded." | |
elsif wanted_versions.size > 0 && !wanted_versions.include?(loaded_version) | |
"You patched #{name} #{GemPatch.send(:versions_to_sentence, wanted_versions)} in #{caller.first} but version #{loaded_version} was loaded. Is your patch still applicable?" | |
end | |
raise GemPatchError, error if error && strategy.raise? | |
logger.warn "GemPatch warning: #{error}" if error && respond_to?(:logger) && strategy.warn? | |
yield unless error && strategy.skip? | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'gem_patch' | |
# Raises an error if faker isn't loaded: | |
# | |
patch "faker" do | |
module Faker | |
#... | |
end | |
end | |
# Logs a warning if a version of faker other than 0.3.0 is loaded: | |
# | |
patch "faker 0.3.0", GemPatch::Strategy::WARN do | |
module Faker | |
#... | |
end | |
end | |
# Logs a warning and does not apply the patch if a version of faker other | |
# than 0.2.9 or 0.3.0 is loaded: | |
# | |
patch "faker 0.2.9 0.3.0", GemPatch::Strategy::WARN + GemPatch::Strategy::SKIP do | |
module Faker | |
#... | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment