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,27 @@
1
+ class Integer
2
+ # Ordinalize turns a number into an ordinal string used to denote the
3
+ # position in an ordered sequence such as 1st, 2nd, 3rd, 4th.
4
+ #
5
+ # 1.ordinalize # => "1st"
6
+ # 2.ordinalize # => "2nd"
7
+ # 1002.ordinalize # => "1002nd"
8
+ # 1003.ordinalize # => "1003rd"
9
+ # -11.ordinalize # => "-11th"
10
+ # -1001.ordinalize # => "-1001st"
11
+ def ordinalize
12
+ MotionSupport::Inflector.ordinalize(self)
13
+ end
14
+
15
+ # Ordinal returns the suffix used to denote the position
16
+ # in an ordered sequence such as 1st, 2nd, 3rd, 4th.
17
+ #
18
+ # 1.ordinal # => "st"
19
+ # 2.ordinal # => "nd"
20
+ # 1002.ordinal # => "nd"
21
+ # 1003.ordinal # => "rd"
22
+ # -11.ordinal # => "th"
23
+ # -1001.ordinal # => "st"
24
+ def ordinal
25
+ MotionSupport::Inflector.ordinal(self)
26
+ end
27
+ end
@@ -0,0 +1,10 @@
1
+ class Integer
2
+ # Check whether the integer is evenly divisible by the argument.
3
+ #
4
+ # 0.multiple_of?(0) #=> true
5
+ # 6.multiple_of?(5) #=> false
6
+ # 10.multiple_of?(2) #=> true
7
+ def multiple_of?(number)
8
+ number != 0 ? self % number == 0 : zero?
9
+ end
10
+ end
@@ -0,0 +1,41 @@
1
+ class Integer
2
+ # Enables the use of time calculations and declarations, like <tt>45.minutes +
3
+ # 2.hours + 4.years</tt>.
4
+ #
5
+ # These methods use Time#advance for precise date calculations when using
6
+ # <tt>from_now</tt>, +ago+, etc. as well as adding or subtracting their
7
+ # results from a Time object.
8
+ #
9
+ # # equivalent to Time.now.advance(months: 1)
10
+ # 1.month.from_now
11
+ #
12
+ # # equivalent to Time.now.advance(years: 2)
13
+ # 2.years.from_now
14
+ #
15
+ # # equivalent to Time.now.advance(months: 4, years: 5)
16
+ # (4.months + 5.years).from_now
17
+ #
18
+ # While these methods provide precise calculation when used as in the examples
19
+ # above, care should be taken to note that this is not true if the result of
20
+ # +months+, +years+, etc is converted before use:
21
+ #
22
+ # # equivalent to 30.days.to_i.from_now
23
+ # 1.month.to_i.from_now
24
+ #
25
+ # # equivalent to 365.25.days.to_f.from_now
26
+ # 1.year.to_f.from_now
27
+ #
28
+ # In such cases, Ruby's core
29
+ # Date[http://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and
30
+ # Time[http://ruby-doc.org/stdlib/libdoc/time/rdoc/Time.html] should be used for precision
31
+ # date and time arithmetic.
32
+ def months
33
+ MotionSupport::Duration.new(self * 30.days, [[:months, self]])
34
+ end
35
+ alias :month :months
36
+
37
+ def years
38
+ MotionSupport::Duration.new(self * 365.25.days, [[:years, self]])
39
+ end
40
+ alias :year :years
41
+ end
@@ -0,0 +1,6 @@
1
+ module Kernel
2
+ # class_eval on an object acts like singleton_class.class_eval.
3
+ def class_eval(*args, &block)
4
+ singleton_class.class_eval(*args, &block)
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ class Object
2
+ # Returns an object's metaclass.
3
+ def metaclass
4
+ class << self
5
+ self
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,69 @@
1
+ class Module
2
+ # Encapsulates the common pattern of:
3
+ #
4
+ # alias_method :foo_without_feature, :foo
5
+ # alias_method :foo, :foo_with_feature
6
+ #
7
+ # With this, you simply do:
8
+ #
9
+ # alias_method_chain :foo, :feature
10
+ #
11
+ # And both aliases are set up for you.
12
+ #
13
+ # Query and bang methods (foo?, foo!) keep the same punctuation:
14
+ #
15
+ # alias_method_chain :foo?, :feature
16
+ #
17
+ # is equivalent to
18
+ #
19
+ # alias_method :foo_without_feature?, :foo?
20
+ # alias_method :foo?, :foo_with_feature?
21
+ #
22
+ # so you can safely chain foo, foo?, and foo! with the same feature.
23
+ def alias_method_chain(target, feature)
24
+ # Strip out punctuation on predicates or bang methods since
25
+ # e.g. target?_without_feature is not a valid method name.
26
+ aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
27
+ yield(aliased_target, punctuation) if block_given?
28
+
29
+ with_method = "#{aliased_target}_with_#{feature}#{punctuation}"
30
+ without_method = "#{aliased_target}_without_#{feature}#{punctuation}"
31
+
32
+ alias_method without_method, target
33
+ alias_method target, with_method
34
+
35
+ case
36
+ when public_method_defined?(without_method)
37
+ public target
38
+ when protected_method_defined?(without_method)
39
+ protected target
40
+ when private_method_defined?(without_method)
41
+ private target
42
+ end
43
+ end
44
+
45
+ # Allows you to make aliases for attributes, which includes
46
+ # getter, setter, and query methods.
47
+ #
48
+ # class Content < ActiveRecord::Base
49
+ # # has a title attribute
50
+ # end
51
+ #
52
+ # class Email < Content
53
+ # alias_attribute :subject, :title
54
+ # end
55
+ #
56
+ # e = Email.find(1)
57
+ # e.title # => "Superstars"
58
+ # e.subject # => "Superstars"
59
+ # e.subject? # => true
60
+ # e.subject = "Megastars"
61
+ # e.title # => "Megastars"
62
+ def alias_attribute(new_name, old_name)
63
+ module_exec do
64
+ define_method(new_name) { self.send(old_name) } # def subject; self.title; end
65
+ define_method("#{new_name}?") { self.send("#{old_name}?") } # def subject?; self.title?; end
66
+ define_method("#{new_name}=") { |v| self.send("#{old_name}=", v) } # def subject=(v); self.title = v; end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,19 @@
1
+ class Module
2
+ # A module may or may not have a name.
3
+ #
4
+ # module M; end
5
+ # M.name # => "M"
6
+ #
7
+ # m = Module.new
8
+ # m.name # => nil
9
+ #
10
+ # A module gets a name when it is first assigned to a constant. Either
11
+ # via the +module+ or +class+ keyword or by an explicit assignment:
12
+ #
13
+ # m = Module.new # creates an anonymous module
14
+ # M = m # => m gets a name here as a side-effect
15
+ # m.name # => "M"
16
+ def anonymous?
17
+ name.nil?
18
+ end
19
+ end
@@ -0,0 +1,38 @@
1
+ class Module
2
+ # Declares an attribute reader backed by an internally-named instance variable.
3
+ def attr_internal_reader(*attrs)
4
+ attrs.each {|attr_name| attr_internal_define(attr_name, :reader)}
5
+ end
6
+
7
+ # Declares an attribute writer backed by an internally-named instance variable.
8
+ def attr_internal_writer(*attrs)
9
+ attrs.each {|attr_name| attr_internal_define(attr_name, :writer)}
10
+ end
11
+
12
+ # Declares an attribute reader and writer backed by an internally-named instance
13
+ # variable.
14
+ def attr_internal_accessor(*attrs)
15
+ attr_internal_reader(*attrs)
16
+ attr_internal_writer(*attrs)
17
+ end
18
+ alias_method :attr_internal, :attr_internal_accessor
19
+
20
+ class << self; attr_accessor :attr_internal_naming_format end
21
+ self.attr_internal_naming_format = '@_%s'
22
+
23
+ private
24
+ def attr_internal_ivar_name(attr)
25
+ Module.attr_internal_naming_format % attr
26
+ end
27
+
28
+ def attr_internal_define(attr_name, type)
29
+ internal_name = attr_internal_ivar_name(attr_name).sub(/\A@/, '')
30
+ class_eval do # class_eval is necessary on 1.9 or else the methods a made private
31
+ # use native attr_* methods as they are faster on some Ruby implementations
32
+ send("attr_#{type}", internal_name)
33
+ end
34
+ attr_name, internal_name = "#{attr_name}=", "#{internal_name}=" if type == :writer
35
+ alias_method attr_name, internal_name
36
+ remove_method internal_name
37
+ end
38
+ end
@@ -0,0 +1,64 @@
1
+ class Module
2
+ def mattr_reader(*syms)
3
+ receiver = self
4
+ options = syms.extract_options!
5
+ syms.each do |sym|
6
+ raise NameError.new('invalid attribute name') unless sym =~ /^[_A-Za-z]\w*$/
7
+ class_exec do
8
+ unless class_variable_defined?("@@#{sym}")
9
+ class_variable_set("@@#{sym}", nil)
10
+ end
11
+
12
+ define_singleton_method sym do
13
+ class_variable_get("@@#{sym}")
14
+ end
15
+ end
16
+
17
+ unless options[:instance_reader] == false || options[:instance_accessor] == false
18
+ class_exec do
19
+ define_method sym do
20
+ receiver.class_variable_get("@@#{sym}")
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ def mattr_writer(*syms)
28
+ receiver = self
29
+ options = syms.extract_options!
30
+ syms.each do |sym|
31
+ raise NameError.new('invalid attribute name') unless sym =~ /^[_A-Za-z]\w*$/
32
+ class_exec do
33
+ define_singleton_method "#{sym}=" do |obj|
34
+ class_variable_set("@@#{sym}", obj)
35
+ end
36
+ end
37
+
38
+ unless options[:instance_writer] == false || options[:instance_accessor] == false
39
+ class_exec do
40
+ define_method "#{sym}=" do |obj|
41
+ receiver.class_variable_set("@@#{sym}", obj)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ # Extends the module object with module and instance accessors for class attributes,
49
+ # just like the native attr* accessors for instance attributes.
50
+ #
51
+ # module AppConfiguration
52
+ # mattr_accessor :google_api_key
53
+ #
54
+ # self.google_api_key = "123456789"
55
+ # end
56
+ #
57
+ # AppConfiguration.google_api_key # => "123456789"
58
+ # AppConfiguration.google_api_key = "overriding the api key!"
59
+ # AppConfiguration.google_api_key # => "overriding the api key!"
60
+ def mattr_accessor(*syms)
61
+ mattr_reader(*syms)
62
+ mattr_writer(*syms)
63
+ end
64
+ end
@@ -0,0 +1,175 @@
1
+ class Module
2
+ # Provides a delegate class method to easily expose contained objects' public methods
3
+ # as your own. Pass one or more methods (specified as symbols or strings)
4
+ # and the name of the target object via the <tt>:to</tt> option (also a symbol
5
+ # or string). At least one method and the <tt>:to</tt> option are required.
6
+ #
7
+ # Delegation is particularly useful with Active Record associations:
8
+ #
9
+ # class Greeter < ActiveRecord::Base
10
+ # def hello
11
+ # 'hello'
12
+ # end
13
+ #
14
+ # def goodbye
15
+ # 'goodbye'
16
+ # end
17
+ # end
18
+ #
19
+ # class Foo < ActiveRecord::Base
20
+ # belongs_to :greeter
21
+ # delegate :hello, to: :greeter
22
+ # end
23
+ #
24
+ # Foo.new.hello # => "hello"
25
+ # Foo.new.goodbye # => NoMethodError: undefined method `goodbye' for #<Foo:0x1af30c>
26
+ #
27
+ # Multiple delegates to the same target are allowed:
28
+ #
29
+ # class Foo < ActiveRecord::Base
30
+ # belongs_to :greeter
31
+ # delegate :hello, :goodbye, to: :greeter
32
+ # end
33
+ #
34
+ # Foo.new.goodbye # => "goodbye"
35
+ #
36
+ # Methods can be delegated to instance variables, class variables, or constants
37
+ # by providing them as a symbols:
38
+ #
39
+ # class Foo
40
+ # CONSTANT_ARRAY = [0,1,2,3]
41
+ # @@class_array = [4,5,6,7]
42
+ #
43
+ # def initialize
44
+ # @instance_array = [8,9,10,11]
45
+ # end
46
+ # delegate :sum, to: :CONSTANT_ARRAY
47
+ # delegate :min, to: :@@class_array
48
+ # delegate :max, to: :@instance_array
49
+ # end
50
+ #
51
+ # Foo.new.sum # => 6
52
+ # Foo.new.min # => 4
53
+ # Foo.new.max # => 11
54
+ #
55
+ # It's also possible to delegate a method to the class by using +:class+:
56
+ #
57
+ # class Foo
58
+ # def self.hello
59
+ # "world"
60
+ # end
61
+ #
62
+ # delegate :hello, to: :class
63
+ # end
64
+ #
65
+ # Foo.new.hello # => "world"
66
+ #
67
+ # Delegates can optionally be prefixed using the <tt>:prefix</tt> option. If the value
68
+ # is <tt>true</tt>, the delegate methods are prefixed with the name of the object being
69
+ # delegated to.
70
+ #
71
+ # Person = Struct.new(:name, :address)
72
+ #
73
+ # class Invoice < Struct.new(:client)
74
+ # delegate :name, :address, to: :client, prefix: true
75
+ # end
76
+ #
77
+ # john_doe = Person.new('John Doe', 'Vimmersvej 13')
78
+ # invoice = Invoice.new(john_doe)
79
+ # invoice.client_name # => "John Doe"
80
+ # invoice.client_address # => "Vimmersvej 13"
81
+ #
82
+ # It is also possible to supply a custom prefix.
83
+ #
84
+ # class Invoice < Struct.new(:client)
85
+ # delegate :name, :address, to: :client, prefix: :customer
86
+ # end
87
+ #
88
+ # invoice = Invoice.new(john_doe)
89
+ # invoice.customer_name # => 'John Doe'
90
+ # invoice.customer_address # => 'Vimmersvej 13'
91
+ #
92
+ # If the delegate object is +nil+ an exception is raised, and that happens
93
+ # no matter whether +nil+ responds to the delegated method. You can get a
94
+ # +nil+ instead with the +:allow_nil+ option.
95
+ #
96
+ # class Foo
97
+ # attr_accessor :bar
98
+ # def initialize(bar = nil)
99
+ # @bar = bar
100
+ # end
101
+ # delegate :zoo, to: :bar
102
+ # end
103
+ #
104
+ # Foo.new.zoo # raises NoMethodError exception (you called nil.zoo)
105
+ #
106
+ # class Foo
107
+ # attr_accessor :bar
108
+ # def initialize(bar = nil)
109
+ # @bar = bar
110
+ # end
111
+ # delegate :zoo, to: :bar, allow_nil: true
112
+ # end
113
+ #
114
+ # Foo.new.zoo # returns nil
115
+ def delegate(*methods)
116
+ options = methods.pop
117
+ unless options.is_a?(Hash) && to = options[:to]
118
+ raise ArgumentError, 'Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter).'
119
+ end
120
+
121
+ prefix, allow_nil = options.values_at(:prefix, :allow_nil)
122
+ unguarded = !allow_nil
123
+
124
+ if prefix == true && to =~ /^[^a-z_]/
125
+ raise ArgumentError, 'Can only automatically set the delegation prefix when delegating to a method.'
126
+ end
127
+
128
+ method_prefix = \
129
+ if prefix
130
+ "#{prefix == true ? to : prefix}_"
131
+ else
132
+ ''
133
+ end
134
+
135
+ reference, *hierarchy = to.to_s.split('.')
136
+ entry = resolver =
137
+ case reference
138
+ when 'self'
139
+ ->(_self) { _self }
140
+ when /^@@/
141
+ ->(_self) { _self.class.class_variable_get(reference) }
142
+ when /^@/
143
+ ->(_self) { _self.instance_variable_get(reference) }
144
+ when /^[A-Z]/
145
+ ->(_self) { if reference.to_s =~ /::/ then reference.constantize else _self.class.const_get(reference) end }
146
+ else
147
+ ->(_self) { _self.send(reference) }
148
+ end
149
+ resolver = ->(_self) { hierarchy.reduce(entry.call(_self)) { |obj, method| obj.public_send(method) } } unless hierarchy.empty?
150
+
151
+ methods.each do |method|
152
+ module_exec do
153
+ # def customer_name(*args, &block)
154
+ # begin
155
+ # if unguarded || client || client.respond_to?(:name)
156
+ # client.name(*args, &block)
157
+ # end
158
+ # rescue client.nil? && NoMethodError
159
+ # raise "..."
160
+ # end
161
+ # end
162
+ define_method("#{method_prefix}#{method}") do |*args, &block|
163
+ target = resolver.call(self)
164
+ if unguarded || target || target.respond_to?(method)
165
+ begin
166
+ target.public_send(method, *args, &block)
167
+ rescue target.nil? && NoMethodError # only rescue NoMethodError when target is nil
168
+ raise "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: #{self.inspect}"
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,60 @@
1
+ class Module
2
+ # Returns the name of the module containing this one.
3
+ #
4
+ # M::N.parent_name # => "M"
5
+ def parent_name
6
+ if defined? @parent_name
7
+ @parent_name
8
+ else
9
+ @parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
10
+ end
11
+ end
12
+
13
+ # Returns the module which contains this one according to its name.
14
+ #
15
+ # module M
16
+ # module N
17
+ # end
18
+ # end
19
+ # X = M::N
20
+ #
21
+ # M::N.parent # => M
22
+ # X.parent # => M
23
+ #
24
+ # The parent of top-level and anonymous modules is Object.
25
+ #
26
+ # M.parent # => Object
27
+ # Module.new.parent # => Object
28
+ def parent
29
+ parent_name ? parent_name.constantize : Object
30
+ end
31
+
32
+ # Returns all the parents of this module according to its name, ordered from
33
+ # nested outwards. The receiver is not contained within the result.
34
+ #
35
+ # module M
36
+ # module N
37
+ # end
38
+ # end
39
+ # X = M::N
40
+ #
41
+ # M.parents # => [Object]
42
+ # M::N.parents # => [M, Object]
43
+ # X.parents # => [M, Object]
44
+ def parents
45
+ parents = []
46
+ if parent_name
47
+ parts = parent_name.split('::')
48
+ until parts.empty?
49
+ parents << (parts * '::').constantize
50
+ parts.pop
51
+ end
52
+ end
53
+ parents << Object unless parents.include? Object
54
+ parents
55
+ end
56
+
57
+ def local_constants #:nodoc:
58
+ constants(false)
59
+ end
60
+ end
@@ -0,0 +1,5 @@
1
+ class Module
2
+ def reachable? #:nodoc:
3
+ !anonymous? && name.safe_constantize.equal?(self)
4
+ end
5
+ end
@@ -0,0 +1,12 @@
1
+ class Module
2
+ def remove_possible_method(method)
3
+ if method_defined?(method) || private_method_defined?(method)
4
+ undef_method(method)
5
+ end
6
+ end
7
+
8
+ def redefine_method(method, &block)
9
+ remove_possible_method(method)
10
+ define_method(method, &block)
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ require_relative 'module/delegation'
2
+
3
+ class NSDictionary
4
+ def to_hash
5
+ Hash.new.tap do |h|
6
+ h.replace self
7
+ end
8
+ end
9
+
10
+ delegate :symbolize_keys, :symbolize_keys!, :deep_symbolize_keys, :deep_symbolize_keys!,
11
+ :stringify_keys, :stringify_keys!, :deep_stringify_keys!, :deep_stringify_keys,
12
+ :deep_transform_keys, :deep_transform_keys!,
13
+ :with_indifferent_access, :nested_under_indifferent_access, :to => :to_hash
14
+ end
@@ -0,0 +1,14 @@
1
+ require_relative 'module/delegation'
2
+
3
+ class NSString
4
+ def to_s
5
+ String.new(self)
6
+ end
7
+
8
+ delegate :at, :blank?, :camelcase, :camelize, :classify, :constantize, :dasherize,
9
+ :deconstantize, :demodulize, :exclude?, :first, :foreign_key, :from, :humanize,
10
+ :indent, :indent!, :last, :pluralize, :safe_constantize, :singularize,
11
+ :squish, :squish!, :strip_heredoc, :tableize, :titlecase, :titleize, :to,
12
+ :truncate, :underscore,
13
+ :to => :to_s
14
+ end
@@ -0,0 +1,44 @@
1
+ class Numeric
2
+ KILOBYTE = 1024
3
+ MEGABYTE = KILOBYTE * 1024
4
+ GIGABYTE = MEGABYTE * 1024
5
+ TERABYTE = GIGABYTE * 1024
6
+ PETABYTE = TERABYTE * 1024
7
+ EXABYTE = PETABYTE * 1024
8
+
9
+ # Enables the use of byte calculations and declarations, like 45.bytes + 2.6.megabytes
10
+ def bytes
11
+ self
12
+ end
13
+ alias :byte :bytes
14
+
15
+ def kilobytes
16
+ self * KILOBYTE
17
+ end
18
+ alias :kilobyte :kilobytes
19
+
20
+ def megabytes
21
+ self * MEGABYTE
22
+ end
23
+ alias :megabyte :megabytes
24
+
25
+ def gigabytes
26
+ self * GIGABYTE
27
+ end
28
+ alias :gigabyte :gigabytes
29
+
30
+ def terabytes
31
+ self * TERABYTE
32
+ end
33
+ alias :terabyte :terabytes
34
+
35
+ def petabytes
36
+ self * PETABYTE
37
+ end
38
+ alias :petabyte :petabytes
39
+
40
+ def exabytes
41
+ self * EXABYTE
42
+ end
43
+ alias :exabyte :exabytes
44
+ end
@@ -0,0 +1,49 @@
1
+ class Numeric
2
+ # Provides options for converting numbers into formatted strings.
3
+ # Right now, options are only provided for phone numbers.
4
+ #
5
+ # ==== Options
6
+ #
7
+ # For details on which formats use which options, see MotionSupport::NumberHelper
8
+ #
9
+ # ==== Examples
10
+ #
11
+ # Phone Numbers:
12
+ # 5551234.to_s(:phone) # => 555-1234
13
+ # 1235551234.to_s(:phone) # => 123-555-1234
14
+ # 1235551234.to_s(:phone, area_code: true) # => (123) 555-1234
15
+ # 1235551234.to_s(:phone, delimiter: ' ') # => 123 555 1234
16
+ # 1235551234.to_s(:phone, area_code: true, extension: 555) # => (123) 555-1234 x 555
17
+ # 1235551234.to_s(:phone, country_code: 1) # => +1-123-555-1234
18
+ # 1235551234.to_s(:phone, country_code: 1, extension: 1343, delimiter: '.')
19
+ # # => +1.123.555.1234 x 1343
20
+ def to_formatted_s(format = :default, options = {})
21
+ case format
22
+ when :phone
23
+ return MotionSupport::NumberHelper.number_to_phone(self, options)
24
+ else
25
+ self.to_default_s
26
+ end
27
+ end
28
+
29
+ [Float, Fixnum, Bignum].each do |klass|
30
+ klass.send(:alias_method, :to_default_s, :to_s)
31
+
32
+ klass.send(:define_method, :to_s) do |*args|
33
+ if args[0].is_a?(Symbol)
34
+ format = args[0]
35
+ options = args[1] || {}
36
+
37
+ self.to_formatted_s(format, options)
38
+ else
39
+ to_default_s(*args)
40
+ end
41
+ end
42
+ end
43
+
44
+ # Stub method to return a pseudo-JSON value from a number. It just returns a string by calling to_s.
45
+ # This should work most of the time.
46
+ def to_json
47
+ to_s
48
+ end
49
+ end