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.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/HACKS.md +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +359 -0
- data/Rakefile +14 -0
- data/app/app_delegate.rb +5 -0
- data/examples/Inflector/.gitignore +16 -0
- data/examples/Inflector/Gemfile +5 -0
- data/examples/Inflector/Rakefile +13 -0
- data/examples/Inflector/app/app_delegate.rb +8 -0
- data/examples/Inflector/app/inflections.rb +5 -0
- data/examples/Inflector/app/inflector_view_controller.rb +109 -0
- data/examples/Inflector/app/words_view_controller.rb +101 -0
- data/examples/Inflector/resources/Default-568h@2x.png +0 -0
- data/examples/Inflector/spec/main_spec.rb +9 -0
- data/lib/motion-support/callbacks.rb +8 -0
- data/lib/motion-support/concern.rb +4 -0
- data/lib/motion-support/core_ext/array.rb +10 -0
- data/lib/motion-support/core_ext/class.rb +5 -0
- data/lib/motion-support/core_ext/hash.rb +13 -0
- data/lib/motion-support/core_ext/integer.rb +6 -0
- data/lib/motion-support/core_ext/module.rb +11 -0
- data/lib/motion-support/core_ext/numeric.rb +6 -0
- data/lib/motion-support/core_ext/object.rb +12 -0
- data/lib/motion-support/core_ext/range.rb +5 -0
- data/lib/motion-support/core_ext/string.rb +13 -0
- data/lib/motion-support/core_ext/time.rb +16 -0
- data/lib/motion-support/core_ext.rb +13 -0
- data/lib/motion-support/inflector.rb +8 -0
- data/lib/motion-support.rb +81 -0
- data/motion/_stdlib/array.rb +13 -0
- data/motion/_stdlib/cgi.rb +22 -0
- data/motion/_stdlib/date.rb +81 -0
- data/motion/_stdlib/enumerable.rb +9 -0
- data/motion/_stdlib/time.rb +19 -0
- data/motion/callbacks.rb +511 -0
- data/motion/concern.rb +122 -0
- data/motion/core_ext/array/access.rb +28 -0
- data/motion/core_ext/array/conversions.rb +86 -0
- data/motion/core_ext/array/extract_options.rb +11 -0
- data/motion/core_ext/array/grouping.rb +99 -0
- data/motion/core_ext/array/prepend_and_append.rb +7 -0
- data/motion/core_ext/array/wrap.rb +45 -0
- data/motion/core_ext/array.rb +19 -0
- data/motion/core_ext/class/attribute.rb +119 -0
- data/motion/core_ext/class/attribute_accessors.rb +168 -0
- data/motion/core_ext/date/acts_like.rb +8 -0
- data/motion/core_ext/date/calculations.rb +117 -0
- data/motion/core_ext/date/conversions.rb +56 -0
- data/motion/core_ext/date_and_time/calculations.rb +232 -0
- data/motion/core_ext/enumerable.rb +90 -0
- data/motion/core_ext/hash/deep_delete_if.rb +23 -0
- data/motion/core_ext/hash/deep_merge.rb +27 -0
- data/motion/core_ext/hash/except.rb +15 -0
- data/motion/core_ext/hash/indifferent_access.rb +19 -0
- data/motion/core_ext/hash/keys.rb +150 -0
- data/motion/core_ext/hash/reverse_merge.rb +22 -0
- data/motion/core_ext/hash/slice.rb +40 -0
- data/motion/core_ext/integer/inflections.rb +27 -0
- data/motion/core_ext/integer/multiple.rb +10 -0
- data/motion/core_ext/integer/time.rb +41 -0
- data/motion/core_ext/kernel/singleton_class.rb +6 -0
- data/motion/core_ext/metaclass.rb +8 -0
- data/motion/core_ext/module/aliasing.rb +69 -0
- data/motion/core_ext/module/anonymous.rb +19 -0
- data/motion/core_ext/module/attr_internal.rb +38 -0
- data/motion/core_ext/module/attribute_accessors.rb +64 -0
- data/motion/core_ext/module/delegation.rb +175 -0
- data/motion/core_ext/module/introspection.rb +60 -0
- data/motion/core_ext/module/reachable.rb +5 -0
- data/motion/core_ext/module/remove_method.rb +12 -0
- data/motion/core_ext/ns_dictionary.rb +14 -0
- data/motion/core_ext/ns_string.rb +14 -0
- data/motion/core_ext/numeric/bytes.rb +44 -0
- data/motion/core_ext/numeric/conversions.rb +49 -0
- data/motion/core_ext/numeric/time.rb +75 -0
- data/motion/core_ext/object/acts_like.rb +10 -0
- data/motion/core_ext/object/blank.rb +105 -0
- data/motion/core_ext/object/deep_dup.rb +44 -0
- data/motion/core_ext/object/duplicable.rb +87 -0
- data/motion/core_ext/object/inclusion.rb +15 -0
- data/motion/core_ext/object/instance_variables.rb +28 -0
- data/motion/core_ext/object/to_param.rb +58 -0
- data/motion/core_ext/object/to_query.rb +26 -0
- data/motion/core_ext/object/try.rb +78 -0
- data/motion/core_ext/range/include_range.rb +23 -0
- data/motion/core_ext/range/overlaps.rb +8 -0
- data/motion/core_ext/regexp.rb +5 -0
- data/motion/core_ext/string/access.rb +104 -0
- data/motion/core_ext/string/behavior.rb +6 -0
- data/motion/core_ext/string/exclude.rb +11 -0
- data/motion/core_ext/string/filters.rb +55 -0
- data/motion/core_ext/string/indent.rb +43 -0
- data/motion/core_ext/string/inflections.rb +178 -0
- data/motion/core_ext/string/starts_ends_with.rb +4 -0
- data/motion/core_ext/string/strip.rb +24 -0
- data/motion/core_ext/time/acts_like.rb +8 -0
- data/motion/core_ext/time/calculations.rb +215 -0
- data/motion/core_ext/time/conversions.rb +52 -0
- data/motion/descendants_tracker.rb +50 -0
- data/motion/duration.rb +104 -0
- data/motion/hash_with_indifferent_access.rb +253 -0
- data/motion/inflections.rb +67 -0
- data/motion/inflector/inflections.rb +203 -0
- data/motion/inflector/methods.rb +321 -0
- data/motion/logger.rb +47 -0
- data/motion/number_helper.rb +54 -0
- data/motion/version.rb +3 -0
- data/motion_blender-support.gemspec +21 -0
- data/spec/motion-support/_helpers/constantize_test_cases.rb +75 -0
- data/spec/motion-support/_helpers/inflector_test_cases.rb +270 -0
- data/spec/motion-support/callback_spec.rb +702 -0
- data/spec/motion-support/concern_spec.rb +93 -0
- data/spec/motion-support/core_ext/array/access_spec.rb +29 -0
- data/spec/motion-support/core_ext/array/conversion_spec.rb +60 -0
- data/spec/motion-support/core_ext/array/extract_options_spec.rb +15 -0
- data/spec/motion-support/core_ext/array/grouping_spec.rb +85 -0
- data/spec/motion-support/core_ext/array/prepend_and_append_spec.rb +25 -0
- data/spec/motion-support/core_ext/array/wrap_spec.rb +19 -0
- data/spec/motion-support/core_ext/array_spec.rb +16 -0
- data/spec/motion-support/core_ext/class/attribute_accessor_spec.rb +127 -0
- data/spec/motion-support/core_ext/class/attribute_spec.rb +92 -0
- data/spec/motion-support/core_ext/date/acts_like_spec.rb +11 -0
- data/spec/motion-support/core_ext/date/calculation_spec.rb +186 -0
- data/spec/motion-support/core_ext/date/conversion_spec.rb +18 -0
- data/spec/motion-support/core_ext/date_and_time/calculation_spec.rb +336 -0
- data/spec/motion-support/core_ext/enumerable_spec.rb +130 -0
- data/spec/motion-support/core_ext/hash/deep_delete_if_spec.rb +19 -0
- data/spec/motion-support/core_ext/hash/deep_merge_spec.rb +32 -0
- data/spec/motion-support/core_ext/hash/except_spec.rb +43 -0
- data/spec/motion-support/core_ext/hash/key_spec.rb +236 -0
- data/spec/motion-support/core_ext/hash/reverse_merge_spec.rb +26 -0
- data/spec/motion-support/core_ext/hash/slice_spec.rb +61 -0
- data/spec/motion-support/core_ext/integer/inflection_spec.rb +23 -0
- data/spec/motion-support/core_ext/integer/multiple_spec.rb +19 -0
- data/spec/motion-support/core_ext/kernel/singleton_class_spec.rb +9 -0
- data/spec/motion-support/core_ext/metaclass_spec.rb +9 -0
- data/spec/motion-support/core_ext/module/aliasing_spec.rb +143 -0
- data/spec/motion-support/core_ext/module/anonymous_spec.rb +29 -0
- data/spec/motion-support/core_ext/module/attr_internal_spec.rb +104 -0
- data/spec/motion-support/core_ext/module/attribute_accessor_spec.rb +86 -0
- data/spec/motion-support/core_ext/module/delegation_spec.rb +136 -0
- data/spec/motion-support/core_ext/module/introspection_spec.rb +70 -0
- data/spec/motion-support/core_ext/module/reachable_spec.rb +61 -0
- data/spec/motion-support/core_ext/module/remove_method_spec.rb +25 -0
- data/spec/motion-support/core_ext/numeric/bytes_spec.rb +43 -0
- data/spec/motion-support/core_ext/numeric/conversions_spec.rb +40 -0
- data/spec/motion-support/core_ext/object/acts_like_spec.rb +21 -0
- data/spec/motion-support/core_ext/object/blank_spec.rb +54 -0
- data/spec/motion-support/core_ext/object/deep_dup_spec.rb +54 -0
- data/spec/motion-support/core_ext/object/duplicable_spec.rb +31 -0
- data/spec/motion-support/core_ext/object/inclusion_spec.rb +34 -0
- data/spec/motion-support/core_ext/object/instance_variable_spec.rb +19 -0
- data/spec/motion-support/core_ext/object/to_param_spec.rb +75 -0
- data/spec/motion-support/core_ext/object/to_query_spec.rb +37 -0
- data/spec/motion-support/core_ext/object/try_spec.rb +92 -0
- data/spec/motion-support/core_ext/range/include_range_spec.rb +31 -0
- data/spec/motion-support/core_ext/range/overlap_spec.rb +43 -0
- data/spec/motion-support/core_ext/regexp_spec.rb +7 -0
- data/spec/motion-support/core_ext/string/access_spec.rb +53 -0
- data/spec/motion-support/core_ext/string/behavior_spec.rb +7 -0
- data/spec/motion-support/core_ext/string/exclude_spec.rb +8 -0
- data/spec/motion-support/core_ext/string/filter_spec.rb +49 -0
- data/spec/motion-support/core_ext/string/indent_spec.rb +56 -0
- data/spec/motion-support/core_ext/string/inflection_spec.rb +142 -0
- data/spec/motion-support/core_ext/string/starts_end_with_spec.rb +14 -0
- data/spec/motion-support/core_ext/string/strip_spec.rb +34 -0
- data/spec/motion-support/core_ext/string_spec.rb +88 -0
- data/spec/motion-support/core_ext/time/acts_like_spec.rb +11 -0
- data/spec/motion-support/core_ext/time/calculation_spec.rb +201 -0
- data/spec/motion-support/core_ext/time/conversion_spec.rb +53 -0
- data/spec/motion-support/descendants_tracker_spec.rb +58 -0
- data/spec/motion-support/duration_spec.rb +107 -0
- data/spec/motion-support/hash_with_indifferent_access_spec.rb +605 -0
- data/spec/motion-support/inflector_spec.rb +504 -0
- data/spec/motion-support/ns_dictionary_spec.rb +89 -0
- data/spec/motion-support/ns_string_spec.rb +182 -0
- data/spec/motion-support/number_helper_spec.rb +55 -0
- 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,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,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
|