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).
-
.convert_all_arguments_to_path(mod, skip, *methods) ⇒ Object
Metaprogramming utility to convert all file arguments to paths.
-
.convert_first_argument_to_path(mod, *methods) ⇒ Object
Metaprogramming utility to convert the first file argument to path.
- .convert_to_path(file_or_path) ⇒ Object
-
.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)
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/backports/tools.rb', line 97 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)
124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/backports/tools.rb', line 124 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)
140 141 142 143 144 145 |
# File 'lib/backports/tools.rb', line 140 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 |
.convert_all_arguments_to_path(mod, skip, *methods) ⇒ Object
Metaprogramming utility to convert all file arguments to paths
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/backports/tools.rb', line 73 def self.convert_all_arguments_to_path mod, skip, *methods methods.each do |selector| unless mod.method_defined? selector warn "#{mod}##{selector} is not defined, so arguments can't converted to path" next end first_args = (1..skip).map{|i| "arg_#{i}"}.join(",") + (skip > 0 ? "," : "") alias_method_chain(mod, selector, :potential_path_arguments) do |aliased_target, punctuation| mod.module_eval <<-end_eval def #{aliased_target}_with_potential_path_arguments#{punctuation}(#{first_args}*files, &block) files = files.map{|f| Backports.convert_to_path f} #{aliased_target}_without_potential_path_arguments#{punctuation}(#{first_args}*files, &block) end end_eval end end end |
.convert_first_argument_to_path(mod, *methods) ⇒ Object
Metaprogramming utility to convert the first file argument to path
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/backports/tools.rb', line 47 def self.convert_first_argument_to_path mod,*methods methods.each do |selector| unless mod.method_defined? selector warn "#{mod}##{selector} is not defined, so argument can't converted to path" next end arity = mod.instance_method(selector).arity last_arg = [] if arity < 0 last_arg = ["*rest"] arity = -1-arity end arg_sequence = (["file"] + (1...arity).map{|i| "arg_#{i}"} + last_arg + ["&block"]).join(", ") alias_method_chain(mod, selector, :potential_path_argument) do |aliased_target, punctuation| mod.module_eval <<-end_eval def #{aliased_target}_with_potential_path_argument#{punctuation}(#{arg_sequence}) file = Backports.convert_to_path(file) #{aliased_target}_without_potential_path_argument#{punctuation}(#{arg_sequence}) end end_eval end end end |
.convert_to_path(file_or_path) ⇒ Object
91 92 93 |
# File 'lib/backports/tools.rb', line 91 def self.convert_to_path(file_or_path) coerce_to(file_or_path, String, :to_str) rescue coerce_to(file_or_path, String, :to_path) rescue file_or_path 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 |