hobo_support 1.3.0.RC

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,89 @@
1
+ module Enumerable
2
+
3
+ def map_and_find(not_found=nil)
4
+ each do |x|
5
+ val = yield(x)
6
+ return val if val
7
+ end
8
+ not_found
9
+ end
10
+
11
+ def map_with_index(res=[])
12
+ each_with_index {|x, i| res << yield(x, i)}
13
+ res
14
+ end
15
+
16
+ def build_hash(res={})
17
+ each do |x|
18
+ pair = block_given? ? yield(x) : x
19
+ res[pair.first] = pair.last if pair
20
+ end
21
+ res
22
+ end
23
+
24
+ def map_hash(res={})
25
+ each do |x|
26
+ v = yield x
27
+ res[x] = v
28
+ end
29
+ res
30
+ end
31
+
32
+ def rest
33
+ self[1..-1] || []
34
+ end
35
+
36
+ class MultiSender
37
+
38
+ undef_method(*(instance_methods.map{|m| m.to_s} - %w*__id__ __send__ object_id*))
39
+
40
+ def initialize(enumerable, method)
41
+ @enumerable = enumerable
42
+ @method = method
43
+ end
44
+
45
+ def method_missing(name, *args, &block)
46
+ @enumerable.send(@method) { |x| x.send(name, *args, &block) }
47
+ end
48
+
49
+ end
50
+
51
+ def *()
52
+ MultiSender.new(self, :map)
53
+ end
54
+
55
+ def where
56
+ MultiSender.new(self, :select)
57
+ end
58
+
59
+ def where_not
60
+ MultiSender.new(self, :reject)
61
+ end
62
+
63
+ def drop_while
64
+ drop = 0
65
+ drop += 1 while yield(self[drop])
66
+ self[drop..-1]
67
+ end
68
+
69
+
70
+ def take_while
71
+ take = 0
72
+ take += 1 while yield(self[take])
73
+ self[0..take-1]
74
+ end
75
+
76
+ end
77
+
78
+
79
+ class Object
80
+
81
+ def in?(enum)
82
+ !enum.nil? && enum.include?(self)
83
+ end
84
+
85
+ def not_in?(enum)
86
+ enum.nil? || !enum.include?(self)
87
+ end
88
+
89
+ end
@@ -0,0 +1,21 @@
1
+ # --- Fix Chronic - can't parse '12th Jan' --- #
2
+ begin
3
+ require 'chronic'
4
+
5
+ module Chronic
6
+
7
+ class << self
8
+ def parse_with_hobo_fix(s, *options)
9
+ if s =~ /^\s*\d+\s*(st|nd|rd|th)\s+[a-zA-Z]+(\s+\d+)?\s*$/
10
+ s = s.sub(/\s*\d+(st|nd|rd|th)/) {|s| s[0..-3]}
11
+ end
12
+
13
+ # Chronic can't parse '1/1/2008 1:00' or '1/1/2008 1:00 PM',
14
+ # so convert them to '1/1/2008 @ 1:00' and '1/1/2008 @ 1:00 PM'
15
+ s = s.sub(/^\s*(\d+\/\d+\/\d+)\s+(\d+:\d+.*)/, '\1 @ \2')
16
+ parse_without_hobo_fix(s, *options)
17
+ end
18
+ alias_method_chain :parse, :hobo_fix
19
+ end
20
+ end
21
+ rescue LoadError; end
@@ -0,0 +1,37 @@
1
+ class Module
2
+
3
+ # Custom alias_method_chain that won't cause inifinite recursion if
4
+ # called twice.
5
+ # Calling alias_method_chain on alias_method_chain
6
+ # was just way to confusing, so I copied it :-/
7
+ def alias_method_chain(target, feature)
8
+ # Strip out punctuation on predicates or bang methods since
9
+ # e.g. target?_without_feature is not a valid method name.
10
+ aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
11
+ yield(aliased_target, punctuation) if block_given?
12
+ without = "#{aliased_target}_without_#{feature}#{punctuation}"
13
+ unless method_defined?(without)
14
+ alias_method without, target
15
+ alias_method target, "#{aliased_target}_with_#{feature}#{punctuation}"
16
+ end
17
+ end
18
+
19
+
20
+ # Fix delegate so it doesn't go bang if 'to' is nil
21
+ def delegate(*methods)
22
+ options = methods.pop
23
+ unless options.is_a?(Hash) && to = options[:to]
24
+ raise ArgumentError, ("Delegation needs a target. Supply an options hash with a :to key" +
25
+ "as the last argument (e.g. delegate :hello, :to => :greeter).")
26
+ end
27
+
28
+ methods.each do |method|
29
+ module_eval(<<-EOS, "(__DELEGATION__)", 1)
30
+ def #{method}(*args, &block)
31
+ (_to = #{to}) && _to.__send__(#{method.inspect}, *args, &block)
32
+ end
33
+ EOS
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,13 @@
1
+ # --- Fix pp dumps - these break sometimes without this --- #
2
+ require 'pp'
3
+ module PP::ObjectMixin
4
+
5
+ alias_method :orig_pretty_print, :pretty_print
6
+ def pretty_print(q)
7
+ orig_pretty_print(q)
8
+ rescue
9
+ "[#PP-ERROR#]"
10
+ end
11
+
12
+ end
13
+
@@ -0,0 +1,124 @@
1
+ class Hash
2
+
3
+ def select_hash(&b)
4
+ res = {}
5
+ each {|k,v| res[k] = v if (b.arity == 1 ? yield(v) : yield(k, v)) }
6
+ res
7
+ end
8
+
9
+
10
+ def map_hash(&b)
11
+ res = {}
12
+ each {|k,v| res[k] = b.arity == 1 ? yield(v) : yield(k, v) }
13
+ res
14
+ end
15
+
16
+ def partition_hash(keys=nil)
17
+ yes = {}
18
+ no = {}
19
+ each do |k,v|
20
+ if block_given? ? yield(k,v) : keys.include?(k)
21
+ yes[k] = v
22
+ else
23
+ no[k] = v
24
+ end
25
+ end
26
+ [yes, no]
27
+ end
28
+
29
+ def recursive_update(hash)
30
+ hash.each_pair do |key, value|
31
+ current = self[key]
32
+ if current.is_a?(Hash) and value.is_a?(Hash)
33
+ current.recursive_update(value)
34
+ else
35
+ self[key] = value
36
+ end
37
+ end
38
+ end
39
+
40
+ def -(keys)
41
+ res = {}
42
+ each_pair {|k, v| res[k] = v unless k.in?(keys)}
43
+ res
44
+ end
45
+
46
+ def &(keys)
47
+ res = {}
48
+ keys.each {|k| res[k] = self[k] if has_key?(k)}
49
+ res
50
+ end
51
+
52
+ alias_method :| , :merge
53
+
54
+ def get(*args)
55
+ args.map {|a| self[a] }
56
+ end
57
+
58
+ def compact
59
+ res = {}
60
+ each { |k, v| res[k] = v unless v.nil? }
61
+ res
62
+ end
63
+
64
+ def compact!
65
+ keys.each { |k| delete(k) if self[k].nil? }
66
+ end
67
+
68
+ # Ruby 1.9.1 complains about the use of index and recommends key
69
+ # but Ruby 1.8 doesn't have key. Add it.
70
+ alias_method(:key, :index) unless method_defined?(:key)
71
+
72
+ end
73
+
74
+
75
+ # HashWithIndifferentAccess from ActiveSupport needs different
76
+ # versions of these
77
+
78
+ if defined? HashWithIndifferentAccess
79
+
80
+ class HashWithIndifferentAccess
81
+
82
+ def -(keys)
83
+ res = HashWithIndifferentAccess.new
84
+ keys = keys.map {|k| k.is_a?(Symbol) ? k.to_s : k }
85
+ each_pair { |k, v| res[k] = v unless k.in?(keys) }
86
+ res
87
+ end
88
+
89
+ def &(keys)
90
+ res = HashWithIndifferentAccess.new
91
+ keys.each do |k|
92
+ k = k.to_s if k.is_a?(Symbol)
93
+ res[k] = self[k] if has_key?(k)
94
+ end
95
+ res
96
+ end
97
+
98
+ def partition_hash(keys=nil)
99
+ keys = keys._?.map {|k| k.is_a?(Symbol) ? k.to_s : k }
100
+ yes = HashWithIndifferentAccess.new
101
+ no = HashWithIndifferentAccess.new
102
+ each do |k,v|
103
+ if block_given? ? yield(k,v) : keys.include?(k)
104
+ yes[k] = v
105
+ else
106
+ no[k] = v
107
+ end
108
+ end
109
+ [yes, no]
110
+ end
111
+
112
+ end
113
+
114
+ end
115
+
116
+ if defined? ActiveSupport
117
+ class ActiveSupport::OrderedHash
118
+ alias each_pair each
119
+
120
+ def first
121
+ empty? ? nil : [keys.first, values.first]
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,15 @@
1
+ class TrueClass
2
+
3
+ def implies(x=nil)
4
+ block_given? ? yield : x
5
+ end
6
+
7
+ end
8
+
9
+ class FalseClass
10
+
11
+ def implies(x)
12
+ true
13
+ end
14
+
15
+ end
@@ -0,0 +1,16 @@
1
+ module Kernel
2
+
3
+ def dbg(*args)
4
+ puts "---DEBUG---"
5
+ args.each do |a|
6
+ if a.is_a?(String) && a =~ /\n/
7
+ puts %("""\n) + a + %(\n"""\n)
8
+ else
9
+ p a
10
+ end
11
+ end
12
+ puts "-----------"
13
+ args.first
14
+ end
15
+
16
+ end
@@ -0,0 +1,28 @@
1
+ # Thanks to _why
2
+
3
+ class Object
4
+
5
+ def metaclass; class << self; self; end; end
6
+
7
+ def meta_eval(src=nil, &blk)
8
+ if src
9
+ metaclass.instance_eval(src)
10
+ else
11
+ metaclass.instance_eval &blk
12
+ end
13
+ end
14
+
15
+ def metaclass_eval(src=nil, &blk)
16
+ if src
17
+ metaclass.class_eval(src)
18
+ else
19
+ metaclass.class_eval &blk
20
+ end
21
+ end
22
+
23
+ # Adds methods to a metaclass
24
+ def meta_def(name, &blk)
25
+ meta_eval { define_method name, &blk }
26
+ end
27
+
28
+ end
@@ -0,0 +1,117 @@
1
+ # The dot operator calls methods on objects. Power Dots are dots with extra features
2
+ #
3
+ # .? calls a method if the receiver is not nil, returns nil
4
+ # otherwise. We have to write it ._?. in order to be valid Ruby
5
+ #
6
+ # .try. calls a method only if the recipient responds to that method
7
+
8
+ require 'delegate'
9
+ require 'singleton'
10
+ require 'blankslate'
11
+
12
+ module HoboSupport
13
+ def self.hobo_try(this, *args, &block)
14
+ if args.length==0
15
+ # Hobo style try
16
+ CallIfAvailable.new(this)
17
+ else
18
+ # activesupport 2.3 style try
19
+ this.send(*args, &block)
20
+ end
21
+ end
22
+ end
23
+
24
+ class Object
25
+
26
+ def _?()
27
+ self
28
+ end
29
+
30
+ def try(*args, &block)
31
+ HoboSupport.hobo_try(self, *args, &block)
32
+ end
33
+
34
+ end
35
+
36
+
37
+ class NilClass
38
+ def _?()
39
+ SafeNil.instance
40
+ end
41
+
42
+
43
+ def try(*args)
44
+ if args.length==0
45
+ # Hobo style try
46
+ CallIfAvailable.new(self)
47
+ else
48
+ # activesupport 2.3 style try
49
+ nil
50
+ end
51
+ end
52
+
53
+ end
54
+
55
+
56
+ class SafeNil
57
+ include Singleton
58
+
59
+ begin
60
+ old_verbose, $VERBOSE = $VERBOSE, nil # just like Rails silence_warnings: suppress "warning: undefining `object_id' may cause serious problem"
61
+ instance_methods.each { |m| undef_method m unless m[0,2] == '__' }
62
+ ensure
63
+ $VERBOSE = old_verbose
64
+ end
65
+
66
+ def method_missing(method, *args, &b)
67
+ return nil
68
+ end
69
+ end
70
+
71
+
72
+ alias DelegateClass_without_safe_nil DelegateClass
73
+ def DelegateClass(klass)
74
+ c = DelegateClass_without_safe_nil(klass)
75
+ c.class_eval do
76
+ def _?
77
+ self
78
+ end
79
+ end
80
+ c
81
+ end
82
+
83
+
84
+ class CallIfAvailable < BlankSlate
85
+
86
+ def initialize(target)
87
+ @target = target
88
+ end
89
+
90
+ def method_missing(name, *args, &b)
91
+ @target.send(name, *args, &b) if @target.respond_to?(name)
92
+ end
93
+
94
+ end
95
+
96
+ module ActiveRecord
97
+ module Associations
98
+ class AssociationProxy
99
+
100
+ # we need to make sure we don't trigger AssociationCollections' method_missing
101
+ def try(*args, &block)
102
+ HoboSupport.hobo_try(self, *args, &block)
103
+ end
104
+ end
105
+ end
106
+
107
+ module NamedScope
108
+ class Scope
109
+ # we need to make sure we don't trigger AssociationCollections' method_missing
110
+ def try(*args, &block)
111
+ HoboSupport.hobo_try(self, *args, &block)
112
+ end
113
+ end
114
+ end
115
+
116
+ end
117
+