motion_blender-support 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (182) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.yardopts +1 -0
  4. data/Gemfile +4 -0
  5. data/HACKS.md +7 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +359 -0
  8. data/Rakefile +14 -0
  9. data/app/app_delegate.rb +5 -0
  10. data/examples/Inflector/.gitignore +16 -0
  11. data/examples/Inflector/Gemfile +5 -0
  12. data/examples/Inflector/Rakefile +13 -0
  13. data/examples/Inflector/app/app_delegate.rb +8 -0
  14. data/examples/Inflector/app/inflections.rb +5 -0
  15. data/examples/Inflector/app/inflector_view_controller.rb +109 -0
  16. data/examples/Inflector/app/words_view_controller.rb +101 -0
  17. data/examples/Inflector/resources/Default-568h@2x.png +0 -0
  18. data/examples/Inflector/spec/main_spec.rb +9 -0
  19. data/lib/motion-support/callbacks.rb +8 -0
  20. data/lib/motion-support/concern.rb +4 -0
  21. data/lib/motion-support/core_ext/array.rb +10 -0
  22. data/lib/motion-support/core_ext/class.rb +5 -0
  23. data/lib/motion-support/core_ext/hash.rb +13 -0
  24. data/lib/motion-support/core_ext/integer.rb +6 -0
  25. data/lib/motion-support/core_ext/module.rb +11 -0
  26. data/lib/motion-support/core_ext/numeric.rb +6 -0
  27. data/lib/motion-support/core_ext/object.rb +12 -0
  28. data/lib/motion-support/core_ext/range.rb +5 -0
  29. data/lib/motion-support/core_ext/string.rb +13 -0
  30. data/lib/motion-support/core_ext/time.rb +16 -0
  31. data/lib/motion-support/core_ext.rb +13 -0
  32. data/lib/motion-support/inflector.rb +8 -0
  33. data/lib/motion-support.rb +81 -0
  34. data/motion/_stdlib/array.rb +13 -0
  35. data/motion/_stdlib/cgi.rb +22 -0
  36. data/motion/_stdlib/date.rb +81 -0
  37. data/motion/_stdlib/enumerable.rb +9 -0
  38. data/motion/_stdlib/time.rb +19 -0
  39. data/motion/callbacks.rb +511 -0
  40. data/motion/concern.rb +122 -0
  41. data/motion/core_ext/array/access.rb +28 -0
  42. data/motion/core_ext/array/conversions.rb +86 -0
  43. data/motion/core_ext/array/extract_options.rb +11 -0
  44. data/motion/core_ext/array/grouping.rb +99 -0
  45. data/motion/core_ext/array/prepend_and_append.rb +7 -0
  46. data/motion/core_ext/array/wrap.rb +45 -0
  47. data/motion/core_ext/array.rb +19 -0
  48. data/motion/core_ext/class/attribute.rb +119 -0
  49. data/motion/core_ext/class/attribute_accessors.rb +168 -0
  50. data/motion/core_ext/date/acts_like.rb +8 -0
  51. data/motion/core_ext/date/calculations.rb +117 -0
  52. data/motion/core_ext/date/conversions.rb +56 -0
  53. data/motion/core_ext/date_and_time/calculations.rb +232 -0
  54. data/motion/core_ext/enumerable.rb +90 -0
  55. data/motion/core_ext/hash/deep_delete_if.rb +23 -0
  56. data/motion/core_ext/hash/deep_merge.rb +27 -0
  57. data/motion/core_ext/hash/except.rb +15 -0
  58. data/motion/core_ext/hash/indifferent_access.rb +19 -0
  59. data/motion/core_ext/hash/keys.rb +150 -0
  60. data/motion/core_ext/hash/reverse_merge.rb +22 -0
  61. data/motion/core_ext/hash/slice.rb +40 -0
  62. data/motion/core_ext/integer/inflections.rb +27 -0
  63. data/motion/core_ext/integer/multiple.rb +10 -0
  64. data/motion/core_ext/integer/time.rb +41 -0
  65. data/motion/core_ext/kernel/singleton_class.rb +6 -0
  66. data/motion/core_ext/metaclass.rb +8 -0
  67. data/motion/core_ext/module/aliasing.rb +69 -0
  68. data/motion/core_ext/module/anonymous.rb +19 -0
  69. data/motion/core_ext/module/attr_internal.rb +38 -0
  70. data/motion/core_ext/module/attribute_accessors.rb +64 -0
  71. data/motion/core_ext/module/delegation.rb +175 -0
  72. data/motion/core_ext/module/introspection.rb +60 -0
  73. data/motion/core_ext/module/reachable.rb +5 -0
  74. data/motion/core_ext/module/remove_method.rb +12 -0
  75. data/motion/core_ext/ns_dictionary.rb +14 -0
  76. data/motion/core_ext/ns_string.rb +14 -0
  77. data/motion/core_ext/numeric/bytes.rb +44 -0
  78. data/motion/core_ext/numeric/conversions.rb +49 -0
  79. data/motion/core_ext/numeric/time.rb +75 -0
  80. data/motion/core_ext/object/acts_like.rb +10 -0
  81. data/motion/core_ext/object/blank.rb +105 -0
  82. data/motion/core_ext/object/deep_dup.rb +44 -0
  83. data/motion/core_ext/object/duplicable.rb +87 -0
  84. data/motion/core_ext/object/inclusion.rb +15 -0
  85. data/motion/core_ext/object/instance_variables.rb +28 -0
  86. data/motion/core_ext/object/to_param.rb +58 -0
  87. data/motion/core_ext/object/to_query.rb +26 -0
  88. data/motion/core_ext/object/try.rb +78 -0
  89. data/motion/core_ext/range/include_range.rb +23 -0
  90. data/motion/core_ext/range/overlaps.rb +8 -0
  91. data/motion/core_ext/regexp.rb +5 -0
  92. data/motion/core_ext/string/access.rb +104 -0
  93. data/motion/core_ext/string/behavior.rb +6 -0
  94. data/motion/core_ext/string/exclude.rb +11 -0
  95. data/motion/core_ext/string/filters.rb +55 -0
  96. data/motion/core_ext/string/indent.rb +43 -0
  97. data/motion/core_ext/string/inflections.rb +178 -0
  98. data/motion/core_ext/string/starts_ends_with.rb +4 -0
  99. data/motion/core_ext/string/strip.rb +24 -0
  100. data/motion/core_ext/time/acts_like.rb +8 -0
  101. data/motion/core_ext/time/calculations.rb +215 -0
  102. data/motion/core_ext/time/conversions.rb +52 -0
  103. data/motion/descendants_tracker.rb +50 -0
  104. data/motion/duration.rb +104 -0
  105. data/motion/hash_with_indifferent_access.rb +253 -0
  106. data/motion/inflections.rb +67 -0
  107. data/motion/inflector/inflections.rb +203 -0
  108. data/motion/inflector/methods.rb +321 -0
  109. data/motion/logger.rb +47 -0
  110. data/motion/number_helper.rb +54 -0
  111. data/motion/version.rb +3 -0
  112. data/motion_blender-support.gemspec +21 -0
  113. data/spec/motion-support/_helpers/constantize_test_cases.rb +75 -0
  114. data/spec/motion-support/_helpers/inflector_test_cases.rb +270 -0
  115. data/spec/motion-support/callback_spec.rb +702 -0
  116. data/spec/motion-support/concern_spec.rb +93 -0
  117. data/spec/motion-support/core_ext/array/access_spec.rb +29 -0
  118. data/spec/motion-support/core_ext/array/conversion_spec.rb +60 -0
  119. data/spec/motion-support/core_ext/array/extract_options_spec.rb +15 -0
  120. data/spec/motion-support/core_ext/array/grouping_spec.rb +85 -0
  121. data/spec/motion-support/core_ext/array/prepend_and_append_spec.rb +25 -0
  122. data/spec/motion-support/core_ext/array/wrap_spec.rb +19 -0
  123. data/spec/motion-support/core_ext/array_spec.rb +16 -0
  124. data/spec/motion-support/core_ext/class/attribute_accessor_spec.rb +127 -0
  125. data/spec/motion-support/core_ext/class/attribute_spec.rb +92 -0
  126. data/spec/motion-support/core_ext/date/acts_like_spec.rb +11 -0
  127. data/spec/motion-support/core_ext/date/calculation_spec.rb +186 -0
  128. data/spec/motion-support/core_ext/date/conversion_spec.rb +18 -0
  129. data/spec/motion-support/core_ext/date_and_time/calculation_spec.rb +336 -0
  130. data/spec/motion-support/core_ext/enumerable_spec.rb +130 -0
  131. data/spec/motion-support/core_ext/hash/deep_delete_if_spec.rb +19 -0
  132. data/spec/motion-support/core_ext/hash/deep_merge_spec.rb +32 -0
  133. data/spec/motion-support/core_ext/hash/except_spec.rb +43 -0
  134. data/spec/motion-support/core_ext/hash/key_spec.rb +236 -0
  135. data/spec/motion-support/core_ext/hash/reverse_merge_spec.rb +26 -0
  136. data/spec/motion-support/core_ext/hash/slice_spec.rb +61 -0
  137. data/spec/motion-support/core_ext/integer/inflection_spec.rb +23 -0
  138. data/spec/motion-support/core_ext/integer/multiple_spec.rb +19 -0
  139. data/spec/motion-support/core_ext/kernel/singleton_class_spec.rb +9 -0
  140. data/spec/motion-support/core_ext/metaclass_spec.rb +9 -0
  141. data/spec/motion-support/core_ext/module/aliasing_spec.rb +143 -0
  142. data/spec/motion-support/core_ext/module/anonymous_spec.rb +29 -0
  143. data/spec/motion-support/core_ext/module/attr_internal_spec.rb +104 -0
  144. data/spec/motion-support/core_ext/module/attribute_accessor_spec.rb +86 -0
  145. data/spec/motion-support/core_ext/module/delegation_spec.rb +136 -0
  146. data/spec/motion-support/core_ext/module/introspection_spec.rb +70 -0
  147. data/spec/motion-support/core_ext/module/reachable_spec.rb +61 -0
  148. data/spec/motion-support/core_ext/module/remove_method_spec.rb +25 -0
  149. data/spec/motion-support/core_ext/numeric/bytes_spec.rb +43 -0
  150. data/spec/motion-support/core_ext/numeric/conversions_spec.rb +40 -0
  151. data/spec/motion-support/core_ext/object/acts_like_spec.rb +21 -0
  152. data/spec/motion-support/core_ext/object/blank_spec.rb +54 -0
  153. data/spec/motion-support/core_ext/object/deep_dup_spec.rb +54 -0
  154. data/spec/motion-support/core_ext/object/duplicable_spec.rb +31 -0
  155. data/spec/motion-support/core_ext/object/inclusion_spec.rb +34 -0
  156. data/spec/motion-support/core_ext/object/instance_variable_spec.rb +19 -0
  157. data/spec/motion-support/core_ext/object/to_param_spec.rb +75 -0
  158. data/spec/motion-support/core_ext/object/to_query_spec.rb +37 -0
  159. data/spec/motion-support/core_ext/object/try_spec.rb +92 -0
  160. data/spec/motion-support/core_ext/range/include_range_spec.rb +31 -0
  161. data/spec/motion-support/core_ext/range/overlap_spec.rb +43 -0
  162. data/spec/motion-support/core_ext/regexp_spec.rb +7 -0
  163. data/spec/motion-support/core_ext/string/access_spec.rb +53 -0
  164. data/spec/motion-support/core_ext/string/behavior_spec.rb +7 -0
  165. data/spec/motion-support/core_ext/string/exclude_spec.rb +8 -0
  166. data/spec/motion-support/core_ext/string/filter_spec.rb +49 -0
  167. data/spec/motion-support/core_ext/string/indent_spec.rb +56 -0
  168. data/spec/motion-support/core_ext/string/inflection_spec.rb +142 -0
  169. data/spec/motion-support/core_ext/string/starts_end_with_spec.rb +14 -0
  170. data/spec/motion-support/core_ext/string/strip_spec.rb +34 -0
  171. data/spec/motion-support/core_ext/string_spec.rb +88 -0
  172. data/spec/motion-support/core_ext/time/acts_like_spec.rb +11 -0
  173. data/spec/motion-support/core_ext/time/calculation_spec.rb +201 -0
  174. data/spec/motion-support/core_ext/time/conversion_spec.rb +53 -0
  175. data/spec/motion-support/descendants_tracker_spec.rb +58 -0
  176. data/spec/motion-support/duration_spec.rb +107 -0
  177. data/spec/motion-support/hash_with_indifferent_access_spec.rb +605 -0
  178. data/spec/motion-support/inflector_spec.rb +504 -0
  179. data/spec/motion-support/ns_dictionary_spec.rb +89 -0
  180. data/spec/motion-support/ns_string_spec.rb +182 -0
  181. data/spec/motion-support/number_helper_spec.rb +55 -0
  182. metadata +352 -0
@@ -0,0 +1,75 @@
1
+ class Numeric
2
+ # Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years.
3
+ #
4
+ # These methods use Time#advance for precise date calculations when using from_now, ago, etc.
5
+ # as well as adding or subtracting their results from a Time object. For example:
6
+ #
7
+ # # equivalent to Time.now.advance(months: 1)
8
+ # 1.month.from_now
9
+ #
10
+ # # equivalent to Time.now.advance(years: 2)
11
+ # 2.years.from_now
12
+ #
13
+ # # equivalent to Time.now.advance(months: 4, years: 5)
14
+ # (4.months + 5.years).from_now
15
+ #
16
+ # While these methods provide precise calculation when used as in the examples above, care
17
+ # should be taken to note that this is not true if the result of `months', `years', etc is
18
+ # converted before use:
19
+ #
20
+ # # equivalent to 30.days.to_i.from_now
21
+ # 1.month.to_i.from_now
22
+ #
23
+ # # equivalent to 365.25.days.to_f.from_now
24
+ # 1.year.to_f.from_now
25
+ #
26
+ # In such cases, Ruby's core
27
+ # Date[http://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and
28
+ # Time[http://ruby-doc.org/stdlib/libdoc/time/rdoc/Time.html] should be used for precision
29
+ # date and time arithmetic.
30
+ def seconds
31
+ MotionSupport::Duration.new(self, [[:seconds, self]])
32
+ end
33
+ alias :second :seconds
34
+
35
+ def minutes
36
+ MotionSupport::Duration.new(self * 60, [[:seconds, self * 60]])
37
+ end
38
+ alias :minute :minutes
39
+
40
+ def hours
41
+ MotionSupport::Duration.new(self * 3600, [[:seconds, self * 3600]])
42
+ end
43
+ alias :hour :hours
44
+
45
+ def days
46
+ MotionSupport::Duration.new(self * 24.hours, [[:days, self]])
47
+ end
48
+ alias :day :days
49
+
50
+ def weeks
51
+ MotionSupport::Duration.new(self * 7.days, [[:days, self * 7]])
52
+ end
53
+ alias :week :weeks
54
+
55
+ def fortnights
56
+ MotionSupport::Duration.new(self * 2.weeks, [[:days, self * 14]])
57
+ end
58
+ alias :fortnight :fortnights
59
+
60
+ # Reads best without arguments: 10.minutes.ago
61
+ def ago(time = ::Time.now)
62
+ time - self
63
+ end
64
+
65
+ # Reads best with argument: 10.minutes.until(time)
66
+ alias :until :ago
67
+
68
+ # Reads best with argument: 10.minutes.since(time)
69
+ def since(time = ::Time.now)
70
+ time + self
71
+ end
72
+
73
+ # Reads best without arguments: 10.minutes.from_now
74
+ alias :from_now :since
75
+ end
@@ -0,0 +1,10 @@
1
+ class Object
2
+ # A duck-type assistant method. For example, Active Support extends Date
3
+ # to define an <tt>acts_like_date?</tt> method, and extends Time to define
4
+ # <tt>acts_like_time?</tt>. As a result, we can do <tt>x.acts_like?(:time)</tt> and
5
+ # <tt>x.acts_like?(:date)</tt> to do duck-type-safe comparisons, since classes that
6
+ # we want to act like Time simply need to define an <tt>acts_like_time?</tt> method.
7
+ def acts_like?(duck)
8
+ respond_to? :"acts_like_#{duck}?"
9
+ end
10
+ end
@@ -0,0 +1,105 @@
1
+ # encoding: utf-8
2
+
3
+ class Object
4
+ # An object is blank if it's false, empty, or a whitespace string.
5
+ # For example, '', ' ', +nil+, [], and {} are all blank.
6
+ #
7
+ # This simplifies:
8
+ #
9
+ # if address.nil? || address.empty?
10
+ #
11
+ # ...to:
12
+ #
13
+ # if address.blank?
14
+ def blank?
15
+ respond_to?(:empty?) ? empty? : !self
16
+ end
17
+
18
+ # An object is present if it's not <tt>blank?</tt>.
19
+ def present?
20
+ !blank?
21
+ end
22
+
23
+ # Returns object if it's <tt>present?</tt> otherwise returns +nil+.
24
+ # <tt>object.presence</tt> is equivalent to <tt>object.present? ? object : nil</tt>.
25
+ #
26
+ # This is handy for any representation of objects where blank is the same
27
+ # as not present at all. For example, this simplifies a common check for
28
+ # HTTP POST/query parameters:
29
+ #
30
+ # state = params[:state] if params[:state].present?
31
+ # country = params[:country] if params[:country].present?
32
+ # region = state || country || 'US'
33
+ #
34
+ # ...becomes:
35
+ #
36
+ # region = params[:state].presence || params[:country].presence || 'US'
37
+ def presence
38
+ self if present?
39
+ end
40
+ end
41
+
42
+ class NilClass
43
+ # +nil+ is blank:
44
+ #
45
+ # nil.blank? # => true
46
+ def blank?
47
+ true
48
+ end
49
+ end
50
+
51
+ class FalseClass
52
+ # +false+ is blank:
53
+ #
54
+ # false.blank? # => true
55
+ def blank?
56
+ true
57
+ end
58
+ end
59
+
60
+ class TrueClass
61
+ # +true+ is not blank:
62
+ #
63
+ # true.blank? # => false
64
+ def blank?
65
+ false
66
+ end
67
+ end
68
+
69
+ class Array
70
+ # An array is blank if it's empty:
71
+ #
72
+ # [].blank? # => true
73
+ # [1,2,3].blank? # => false
74
+ alias_method :blank?, :empty?
75
+ end
76
+
77
+ class Hash
78
+ # A hash is blank if it's empty:
79
+ #
80
+ # {}.blank? # => true
81
+ # { key: 'value' }.blank? # => false
82
+ alias_method :blank?, :empty?
83
+ end
84
+
85
+ class String
86
+ # A string is blank if it's empty or contains whitespaces only:
87
+ #
88
+ # ''.blank? # => true
89
+ # ' '.blank? # => true
90
+ # ' '.blank? # => true
91
+ # ' something here '.blank? # => false
92
+ def blank?
93
+ self !~ /[^[:space:]]/
94
+ end
95
+ end
96
+
97
+ class Numeric #:nodoc:
98
+ # No number is blank:
99
+ #
100
+ # 1.blank? # => false
101
+ # 0.blank? # => false
102
+ def blank?
103
+ false
104
+ end
105
+ end
@@ -0,0 +1,44 @@
1
+ class Object
2
+ # Returns a deep copy of object if it's duplicable. If it's
3
+ # not duplicable, returns +self+.
4
+ #
5
+ # object = Object.new
6
+ # dup = object.deep_dup
7
+ # dup.instance_variable_set(:@a, 1)
8
+ #
9
+ # object.instance_variable_defined?(:@a) #=> false
10
+ # dup.instance_variable_defined?(:@a) #=> true
11
+ def deep_dup
12
+ duplicable? ? dup : self
13
+ end
14
+ end
15
+
16
+ class Array
17
+ # Returns a deep copy of array.
18
+ #
19
+ # array = [1, [2, 3]]
20
+ # dup = array.deep_dup
21
+ # dup[1][2] = 4
22
+ #
23
+ # array[1][2] #=> nil
24
+ # dup[1][2] #=> 4
25
+ def deep_dup
26
+ map { |it| it.deep_dup }
27
+ end
28
+ end
29
+
30
+ class Hash
31
+ # Returns a deep copy of hash.
32
+ #
33
+ # hash = { a: { b: 'b' } }
34
+ # dup = hash.deep_dup
35
+ # dup[:a][:c] = 'c'
36
+ #
37
+ # hash[:a][:c] #=> nil
38
+ # dup[:a][:c] #=> "c"
39
+ def deep_dup
40
+ each_with_object(dup) do |(key, value), hash|
41
+ hash[key.deep_dup] = value.deep_dup
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,87 @@
1
+ #--
2
+ # Most objects are cloneable, but not all. For example you can't dup +nil+:
3
+ #
4
+ # nil.dup # => TypeError: can't dup NilClass
5
+ #
6
+ # Classes may signal their instances are not duplicable removing +dup+/+clone+
7
+ # or raising exceptions from them. So, to dup an arbitrary object you normally
8
+ # use an optimistic approach and are ready to catch an exception, say:
9
+ #
10
+ # arbitrary_object.dup rescue object
11
+ #
12
+ # Rails dups objects in a few critical spots where they are not that arbitrary.
13
+ # That rescue is very expensive (like 40 times slower than a predicate), and it
14
+ # is often triggered.
15
+ #
16
+ # That's why we hardcode the following cases and check duplicable? instead of
17
+ # using that rescue idiom.
18
+ #++
19
+ class Object
20
+ # Can you safely dup this object?
21
+ #
22
+ # False for +nil+, +false+, +true+, symbol, and number objects;
23
+ # true otherwise.
24
+ def duplicable?
25
+ true
26
+ end
27
+ end
28
+
29
+ class NilClass
30
+ # +nil+ is not duplicable:
31
+ #
32
+ # nil.duplicable? # => false
33
+ # nil.dup # => TypeError: can't dup NilClass
34
+ def duplicable?
35
+ false
36
+ end
37
+ end
38
+
39
+ class FalseClass
40
+ # +false+ is not duplicable:
41
+ #
42
+ # false.duplicable? # => false
43
+ # false.dup # => TypeError: can't dup FalseClass
44
+ def duplicable?
45
+ false
46
+ end
47
+ end
48
+
49
+ class TrueClass
50
+ # +true+ is not duplicable:
51
+ #
52
+ # true.duplicable? # => false
53
+ # true.dup # => TypeError: can't dup TrueClass
54
+ def duplicable?
55
+ false
56
+ end
57
+ end
58
+
59
+ class Symbol
60
+ # Symbols are not duplicable:
61
+ #
62
+ # :my_symbol.duplicable? # => false
63
+ # :my_symbol.dup # => TypeError: can't dup Symbol
64
+ def duplicable?
65
+ false
66
+ end
67
+ end
68
+
69
+ class Numeric
70
+ # Numbers are not duplicable:
71
+ #
72
+ # 3.duplicable? # => false
73
+ # 3.dup # => TypeError: can't dup Fixnum
74
+ def duplicable?
75
+ false
76
+ end
77
+ end
78
+
79
+ class BigDecimal
80
+ # BigDecimals are not duplicable:
81
+ #
82
+ # BigDecimal.new('4.56').duplicable? # => false
83
+ # BigDecimal.new('4.56').dup # => TypeError: can't dup Fixnum
84
+ def duplicable?
85
+ false
86
+ end
87
+ end
@@ -0,0 +1,15 @@
1
+ class Object
2
+ # Returns true if this object is included in the argument(s). Argument must be
3
+ # any object which responds to +#include?+. Usage:
4
+ #
5
+ # characters = ['Konata', 'Kagami', 'Tsukasa']
6
+ # 'Konata'.in?(characters) # => true
7
+ #
8
+ # This will throw an ArgumentError it doesn't respond to +#include?+.
9
+ def __in_workaround(args)
10
+ args.include?(self)
11
+ rescue NoMethodError
12
+ raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
13
+ end
14
+ alias in? __in_workaround
15
+ end
@@ -0,0 +1,28 @@
1
+ class Object
2
+ # Returns a hash with string keys that maps instance variable names without "@" to their
3
+ # corresponding values.
4
+ #
5
+ # class C
6
+ # def initialize(x, y)
7
+ # @x, @y = x, y
8
+ # end
9
+ # end
10
+ #
11
+ # C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}
12
+ def instance_values
13
+ Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }]
14
+ end
15
+
16
+ # Returns an array of instance variable names as strings including "@".
17
+ #
18
+ # class C
19
+ # def initialize(x, y)
20
+ # @x, @y = x, y
21
+ # end
22
+ # end
23
+ #
24
+ # C.new(0, 1).instance_variable_names # => ["@y", "@x"]
25
+ def instance_variable_names
26
+ instance_variables.map { |var| var.to_s }
27
+ end
28
+ end
@@ -0,0 +1,58 @@
1
+ class Object
2
+ # Alias of <tt>to_s</tt>.
3
+ def to_param
4
+ to_s
5
+ end
6
+ end
7
+
8
+ class NilClass
9
+ # Returns +self+.
10
+ def to_param
11
+ self
12
+ end
13
+ end
14
+
15
+ class TrueClass
16
+ # Returns +self+.
17
+ def to_param
18
+ self
19
+ end
20
+ end
21
+
22
+ class FalseClass
23
+ # Returns +self+.
24
+ def to_param
25
+ self
26
+ end
27
+ end
28
+
29
+ class Array
30
+ # Calls <tt>to_param</tt> on all its elements and joins the result with
31
+ # slashes. This is used by <tt>url_for</tt> in Action Pack.
32
+ def to_param
33
+ collect { |e| e.to_param }.join '/'
34
+ end
35
+ end
36
+
37
+ class Hash
38
+ # Returns a string representation of the receiver suitable for use as a URL
39
+ # query string:
40
+ #
41
+ # {name: 'David', nationality: 'Danish'}.to_param
42
+ # # => "name=David&nationality=Danish"
43
+ #
44
+ # An optional namespace can be passed to enclose the param names:
45
+ #
46
+ # {name: 'David', nationality: 'Danish'}.to_param('user')
47
+ # # => "user[name]=David&user[nationality]=Danish"
48
+ #
49
+ # The string pairs "key=value" that conform the query string
50
+ # are sorted lexicographically in ascending order.
51
+ #
52
+ # This method is also aliased as +to_query+.
53
+ def to_param(namespace = nil)
54
+ collect do |key, value|
55
+ value.to_query(namespace ? "#{namespace}[#{key}]" : key)
56
+ end.sort * '&'
57
+ end
58
+ end
@@ -0,0 +1,26 @@
1
+ require_relative 'to_param'
2
+
3
+ class Object
4
+ # Converts an object into a string suitable for use as a URL query string, using the given <tt>key</tt> as the
5
+ # param name.
6
+ #
7
+ # Note: This method is defined as a default implementation for all Objects for Hash#to_query to work.
8
+ def to_query(key)
9
+ "#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}"
10
+ end
11
+ end
12
+
13
+ class Array
14
+ # Converts an array into a string suitable for use as a URL query string,
15
+ # using the given +key+ as the param name.
16
+ #
17
+ # ['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
18
+ def to_query(key)
19
+ prefix = "#{key}[]"
20
+ collect { |value| value.to_query(prefix) }.join '&'
21
+ end
22
+ end
23
+
24
+ class Hash
25
+ alias_method :to_query, :to_param
26
+ end
@@ -0,0 +1,78 @@
1
+ class Object
2
+ # Invokes the public method whose name goes as first argument just like
3
+ # +public_send+ does, except that if the receiver does not respond to it the
4
+ # call returns +nil+ rather than raising an exception.
5
+ #
6
+ # This method is defined to be able to write
7
+ #
8
+ # @person.try(:name)
9
+ #
10
+ # instead of
11
+ #
12
+ # @person ? @person.name : nil
13
+ #
14
+ # +try+ returns +nil+ when called on +nil+ regardless of whether it responds
15
+ # to the method:
16
+ #
17
+ # nil.try(:to_i) # => nil, rather than 0
18
+ #
19
+ # Arguments and blocks are forwarded to the method if invoked:
20
+ #
21
+ # @posts.try(:each_slice, 2) do |a, b|
22
+ # ...
23
+ # end
24
+ #
25
+ # The number of arguments in the signature must match. If the object responds
26
+ # to the method the call is attempted and +ArgumentError+ is still raised
27
+ # otherwise.
28
+ #
29
+ # If +try+ is called without arguments it yields the receiver to a given
30
+ # block unless it is +nil+:
31
+ #
32
+ # @person.try do |p|
33
+ # ...
34
+ # end
35
+ #
36
+ # Please also note that +try+ is defined on +Object+, therefore it won't work
37
+ # with instances of classes that do not have +Object+ among their ancestors,
38
+ # like direct subclasses of +BasicObject+. For example, using +try+ with
39
+ # +SimpleDelegator+ will delegate +try+ to the target instead of calling it on
40
+ # delegator itself.
41
+ def try(*a, &b)
42
+ if a.empty? && block_given?
43
+ yield self
44
+ else
45
+ public_send(*a, &b) if respond_to?(a.first)
46
+ end
47
+ end
48
+
49
+ # Same as #try, but will raise a NoMethodError exception if the receiving is not nil and
50
+ # does not implemented the tried method.
51
+ def try!(*a, &b)
52
+ if a.empty? && block_given?
53
+ yield self
54
+ else
55
+ public_send(*a, &b)
56
+ end
57
+ end
58
+ end
59
+
60
+ class NilClass
61
+ # Calling +try+ on +nil+ always returns +nil+.
62
+ # It becomes specially helpful when navigating through associations that may return +nil+.
63
+ #
64
+ # nil.try(:name) # => nil
65
+ #
66
+ # Without +try+
67
+ # @person && !@person.children.blank? && @person.children.first.name
68
+ #
69
+ # With +try+
70
+ # @person.try(:children).try(:first).try(:name)
71
+ def try(*args)
72
+ nil
73
+ end
74
+
75
+ def try!(*args)
76
+ nil
77
+ end
78
+ end
@@ -0,0 +1,23 @@
1
+ require_relative '../module/aliasing'
2
+
3
+ class Range
4
+ # Extends the default Range#include? to support range comparisons.
5
+ # (1..5).include?(1..5) # => true
6
+ # (1..5).include?(2..3) # => true
7
+ # (1..5).include?(2..6) # => false
8
+ #
9
+ # The native Range#include? behavior is untouched.
10
+ # ('a'..'f').include?('c') # => true
11
+ # (5..9).include?(11) # => false
12
+ def include_with_range?(value)
13
+ if value.is_a?(::Range)
14
+ # 1...10 includes 1..9 but it does not include 1..10.
15
+ operator = exclude_end? && !value.exclude_end? ? :< : :<=
16
+ include_without_range?(value.first) && value.last.send(operator, last)
17
+ else
18
+ include_without_range?(value)
19
+ end
20
+ end
21
+
22
+ alias_method_chain :include?, :range
23
+ end
@@ -0,0 +1,8 @@
1
+ class Range
2
+ # Compare two ranges and see if they overlap each other
3
+ # (1..5).overlaps?(4..6) # => true
4
+ # (1..5).overlaps?(7..9) # => false
5
+ def overlaps?(other)
6
+ cover?(other.first) || other.cover?(first)
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ class Regexp #:nodoc:
2
+ def multiline?
3
+ options & MULTILINE == MULTILINE
4
+ end
5
+ end
@@ -0,0 +1,104 @@
1
+ class String
2
+ # If you pass a single Fixnum, returns a substring of one character at that
3
+ # position. The first character of the string is at position 0, the next at
4
+ # position 1, and so on. If a range is supplied, a substring containing
5
+ # characters at offsets given by the range is returned. In both cases, if an
6
+ # offset is negative, it is counted from the end of the string. Returns nil
7
+ # if the initial offset falls outside the string. Returns an empty string if
8
+ # the beginning of the range is greater than the end of the string.
9
+ #
10
+ # str = "hello"
11
+ # str.at(0) #=> "h"
12
+ # str.at(1..3) #=> "ell"
13
+ # str.at(-2) #=> "l"
14
+ # str.at(-2..-1) #=> "lo"
15
+ # str.at(5) #=> nil
16
+ # str.at(5..-1) #=> ""
17
+ #
18
+ # If a Regexp is given, the matching portion of the string is returned.
19
+ # If a String is given, that given string is returned if it occurs in
20
+ # the string. In both cases, nil is returned if there is no match.
21
+ #
22
+ # str = "hello"
23
+ # str.at(/lo/) #=> "lo"
24
+ # str.at(/ol/) #=> nil
25
+ # str.at("lo") #=> "lo"
26
+ # str.at("ol") #=> nil
27
+ def at(position)
28
+ self[position]
29
+ end
30
+
31
+ # Returns a substring from the given position to the end of the string.
32
+ # If the position is negative, it is counted from the end of the string.
33
+ #
34
+ # str = "hello"
35
+ # str.from(0) #=> "hello"
36
+ # str.from(3) #=> "lo"
37
+ # str.from(-2) #=> "lo"
38
+ #
39
+ # You can mix it with +to+ method and do fun things like:
40
+ #
41
+ # str = "hello"
42
+ # str.from(0).to(-1) #=> "hello"
43
+ # str.from(1).to(-2) #=> "ell"
44
+ def from(position)
45
+ self[position..-1]
46
+ end
47
+
48
+ # Returns a substring from the beginning of the string to the given position.
49
+ # If the position is negative, it is counted from the end of the string.
50
+ #
51
+ # str = "hello"
52
+ # str.to(0) #=> "h"
53
+ # str.to(3) #=> "hell"
54
+ # str.to(-2) #=> "hell"
55
+ #
56
+ # You can mix it with +from+ method and do fun things like:
57
+ #
58
+ # str = "hello"
59
+ # str.from(0).to(-1) #=> "hello"
60
+ # str.from(1).to(-2) #=> "ell"
61
+ def to(position)
62
+ self[0..position]
63
+ end
64
+
65
+ # Returns the first character. If a limit is supplied, returns a substring
66
+ # from the beginning of the string until it reaches the limit value. If the
67
+ # given limit is greater than or equal to the string length, returns self.
68
+ #
69
+ # str = "hello"
70
+ # str.first #=> "h"
71
+ # str.first(1) #=> "h"
72
+ # str.first(2) #=> "he"
73
+ # str.first(0) #=> ""
74
+ # str.first(6) #=> "hello"
75
+ def first(limit = 1)
76
+ if limit == 0
77
+ ''
78
+ elsif limit >= size
79
+ self
80
+ else
81
+ to(limit - 1)
82
+ end
83
+ end
84
+
85
+ # Returns the last character of the string. If a limit is supplied, returns a substring
86
+ # from the end of the string until it reaches the limit value (counting backwards). If
87
+ # the given limit is greater than or equal to the string length, returns self.
88
+ #
89
+ # str = "hello"
90
+ # str.last #=> "o"
91
+ # str.last(1) #=> "o"
92
+ # str.last(2) #=> "lo"
93
+ # str.last(0) #=> ""
94
+ # str.last(6) #=> "hello"
95
+ def last(limit = 1)
96
+ if limit == 0
97
+ ''
98
+ elsif limit >= size
99
+ self
100
+ else
101
+ from(-limit)
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,6 @@
1
+ class String
2
+ # Enable more predictable duck-typing on String-like classes. See <tt>Object#acts_like?</tt>.
3
+ def acts_like_string?
4
+ true
5
+ end
6
+ end
@@ -0,0 +1,11 @@
1
+ class String
2
+ # The inverse of <tt>String#include?</tt>. Returns true if the string
3
+ # does not include the other string.
4
+ #
5
+ # "hello".exclude? "lo" #=> false
6
+ # "hello".exclude? "ol" #=> true
7
+ # "hello".exclude? ?h #=> false
8
+ def exclude?(string)
9
+ !include?(string)
10
+ end
11
+ end