motion_blender-support 0.2.7

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.
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