Module: Backports
- Defined in:
- lib/backports/tools.rb
Overview
Methods used internally by the backports.
Defined Under Namespace
Classes: Yielder
Constant Summary collapse
- Undefined =
Used internally to make it easy to deal with optional arguments (from Rubinius)
Object.new
Class Method Summary collapse
-
.alias_method_chain(mod, target, feature) ⇒ Object
Modified to avoid polluting Module if so desired (from Rails).
-
.coerce_to(obj, cls, meth) ⇒ Object
Helper method to coerce a value into a specific class.
-
.coerce_to_comparison(a, b, cmp = (a <=> b)) ⇒ Object
Checks for a failed comparison (in which case it throws an ArgumentError) Additionally, it maps any negative value to -1 and any positive value to +1 (from Rubinius).
-
.make_block_optional(mod, *methods) ⇒ Object
Metaprogramming utility to make block optional.
-
.require_relative(relative_feature) ⇒ Object
Adapted from Pragmatic’s “Programming Ruby” (since their version was buggy…).
Class Method Details
.alias_method_chain(mod, target, feature) ⇒ Object
Modified to avoid polluting Module if so desired (from Rails)
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/backports/tools.rb', line 48 def self.alias_method_chain(mod, target, feature) mod.class_eval do # Strip out punctuation on predicates or bang methods since # e.g. target?_without_feature is not a valid method name. aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1 yield(aliased_target, punctuation) if block_given? with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}" alias_method without_method, target alias_method target, with_method case when public_method_defined?(without_method) public target when protected_method_defined?(without_method) protected target when private_method_defined?(without_method) private target end end end |
.coerce_to(obj, cls, meth) ⇒ Object
Helper method to coerce a value into a specific class. Raises a TypeError if the coercion fails or the returned value is not of the right class. (from Rubinius)
75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/backports/tools.rb', line 75 def self.coerce_to(obj, cls, meth) return obj if obj.kind_of?(cls) begin ret = obj.__send__(meth) rescue Exception => e raise TypeError, "Coercion error: #{obj.inspect}.#{meth} => #{cls} failed:\n" \ "(#{e.})" end raise TypeError, "Coercion error: obj.#{meth} did NOT return a #{cls} (was #{ret.class})" unless ret.kind_of? cls ret end |
.coerce_to_comparison(a, b, cmp = (a <=> b)) ⇒ Object
Checks for a failed comparison (in which case it throws an ArgumentError) Additionally, it maps any negative value to -1 and any positive value to +1 (from Rubinius)
91 92 93 94 95 96 |
# File 'lib/backports/tools.rb', line 91 def self.coerce_to_comparison(a, b, cmp = (a <=> b)) raise ArgumentError, "comparison of #{a} with #{b} failed" if cmp.nil? return 1 if cmp > 0 return -1 if cmp < 0 0 end |
.make_block_optional(mod, *methods) ⇒ Object
Metaprogramming utility to make block optional. Tests first if block is already optional when given options
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/backports/tools.rb', line 15 def self.make_block_optional mod,*methods = methods.last.is_a?(Hash) ? methods.pop : {} methods.each do |selector| unless mod.method_defined? selector warn "#{mod}##{selector} is not defined, so block can't be made optional" next end unless .empty? test_on = [:test_on] || self.new next if (test_on.send(selector, *.fetch(:arg, [])) rescue false) end arity = mod.instance_method(selector).arity last_arg = [] if arity < 0 last_arg = ["*rest"] arity = -1-arity end arg_sequence = ((0...arity).map{|i| "arg_#{i}"} + last_arg + ["&block"]).join(", ") alias_method_chain(mod, selector, :optional_block) do |aliased_target, punctuation| mod.module_eval <<-end_eval def #{aliased_target}_with_optional_block#{punctuation}(#{arg_sequence}) return to_enum(:#{aliased_target}_without_optional_block#{punctuation}, #{arg_sequence}) unless block_given? #{aliased_target}_without_optional_block#{punctuation}(#{arg_sequence}) end end_eval end end end |
.require_relative(relative_feature) ⇒ Object
Adapted from Pragmatic’s “Programming Ruby” (since their version was buggy…)
5 6 7 8 9 10 11 |
# File 'lib/backports/tools.rb', line 5 def self.require_relative(relative_feature) file = caller.first.split(/:\d/,2).first if /\A\((.*)\)/ =~ file # eval, etc. raise LoadError, "require_relative is called in #{$1}" end require File.(relative_feature, File.dirname(file)) end |