motion_blender-support 0.2.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|