motion-support 0.1.0 → 0.2.0
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.
- data/.gitignore +3 -0
- data/Gemfile +1 -1
- data/README.md +231 -2
- data/Rakefile +3 -3
- data/app/app_delegate.rb +0 -2
- 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 +120 -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/core_ext/array.rb +13 -0
- data/lib/motion-support/core_ext/class.rb +8 -0
- data/lib/motion-support/core_ext/hash.rb +16 -0
- data/lib/motion-support/core_ext/integer.rb +9 -0
- data/lib/motion-support/core_ext/module.rb +14 -0
- data/lib/motion-support/core_ext/numeric.rb +8 -0
- data/lib/motion-support/core_ext/object.rb +14 -0
- data/lib/motion-support/core_ext/range.rb +8 -0
- data/lib/motion-support/core_ext/string.rb +14 -0
- data/lib/motion-support/core_ext/time.rb +19 -0
- data/lib/motion-support/core_ext.rb +3 -0
- data/lib/motion-support/inflector.rb +12 -156
- data/lib/motion-support.rb +5 -5
- data/motion/_stdlib/cgi.rb +22 -0
- data/motion/_stdlib/date.rb +77 -0
- data/motion/_stdlib/time.rb +19 -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/{lib/motion-support → motion/core_ext}/array.rb +0 -4
- 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_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 +138 -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/{lib/motion-support → motion/core_ext}/metaclass.rb +0 -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 +11 -0
- data/motion/core_ext/numeric/bytes.rb +44 -0
- data/motion/core_ext/numeric/conversions.rb +7 -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 +83 -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 +195 -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/duration.rb +104 -0
- data/motion/hash_with_indifferent_access.rb +251 -0
- data/motion/inflections.rb +67 -0
- data/motion/inflector/inflections.rb +203 -0
- data/motion/inflector/methods.rb +321 -0
- data/{lib/motion-support → motion}/logger.rb +0 -0
- data/{lib/motion-support → motion}/version.rb +1 -1
- data/motion-support.gemspec +2 -2
- data/spec/motion-support/_helpers/constantize_test_cases.rb +75 -0
- data/spec/motion-support/_helpers/inflector_test_cases.rb +313 -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/{array_spec.rb → core_ext/array_spec.rb} +0 -5
- 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_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 +230 -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/{metaclass_spec.rb → core_ext/metaclass_spec.rb} +0 -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/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/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 +48 -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 +54 -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 +474 -35
- data/spec/motion-support/ns_dictionary_spec.rb +29 -0
- metadata +212 -35
- data/lib/motion-support/cattr_accessor.rb +0 -19
- data/lib/motion-support/class_inheritable_accessor.rb +0 -23
- data/lib/motion-support/class_inheritable_array.rb +0 -29
- data/lib/motion-support/hash.rb +0 -31
- data/lib/motion-support/nilclass.rb +0 -5
- data/lib/motion-support/object.rb +0 -17
- data/lib/motion-support/string.rb +0 -71
- data/spec/motion-support/cattr_accessor_spec.rb +0 -49
- data/spec/motion-support/class_inheritable_accessor_spec.rb +0 -49
- data/spec/motion-support/class_inheritable_array_spec.rb +0 -61
- data/spec/motion-support/hash_spec.rb +0 -31
- data/spec/motion-support/nilclass_spec.rb +0 -5
- data/spec/motion-support/object_spec.rb +0 -43
- data/spec/motion-support/string_spec.rb +0 -145
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'motion-require'
|
|
2
|
+
|
|
3
|
+
files = [
|
|
4
|
+
'_stdlib/date',
|
|
5
|
+
'_stdlib/time',
|
|
6
|
+
'core_ext/time/acts_like',
|
|
7
|
+
'core_ext/time/calculations',
|
|
8
|
+
'core_ext/time/conversions',
|
|
9
|
+
'core_ext/date/acts_like',
|
|
10
|
+
'core_ext/date/calculations',
|
|
11
|
+
'core_ext/date/conversions',
|
|
12
|
+
'core_ext/date_and_time/calculations',
|
|
13
|
+
'core_ext/integer/time',
|
|
14
|
+
'core_ext/numeric/time',
|
|
15
|
+
'core_ext/object/acts_like',
|
|
16
|
+
'duration'
|
|
17
|
+
].map { |file| File.expand_path(File.join(File.dirname(__FILE__), "/../../../motion", "#{file}.rb")) }
|
|
18
|
+
|
|
19
|
+
Motion::Require.all(files)
|
|
@@ -1,156 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def reset
|
|
15
|
-
# Put singular-form to plural form transformations here
|
|
16
|
-
@plurals = [
|
|
17
|
-
[/^person$/, 'people'],
|
|
18
|
-
[/^man$/, 'men'],
|
|
19
|
-
[/^child$/, 'children'],
|
|
20
|
-
[/^sex$/, 'sexes'],
|
|
21
|
-
[/^move$/, 'moves'],
|
|
22
|
-
[/^cow$/, 'kine'],
|
|
23
|
-
[/^zombie$/, 'zombies'],
|
|
24
|
-
[/(quiz)$/i, '\1zes'],
|
|
25
|
-
[/^(oxen)$/i, '\1'],
|
|
26
|
-
[/^(ox)$/i, '\1en'],
|
|
27
|
-
[/^(m|l)ice$/i, '\1ice'],
|
|
28
|
-
[/^(m|l)ouse$/i, '\1ice'],
|
|
29
|
-
[/(matr|vert|ind)(?:ix|ex)$/i, '\1ices'],
|
|
30
|
-
[/(x|ch|ss|sh)$/i, '\1es'],
|
|
31
|
-
[/([^aeiouy]|qu)y$/i, '\1ies'],
|
|
32
|
-
[/(hive)$/i, '\1s'],
|
|
33
|
-
[/(?:([^f])fe|([lr])f)$/i, '\1\2ves'],
|
|
34
|
-
[/sis$/i, 'ses'],
|
|
35
|
-
[/([ti])a$/i, '\1a'],
|
|
36
|
-
[/([ti])um$/i, '\1a'],
|
|
37
|
-
[/(buffal|tomat)o$/i, '\1oes'],
|
|
38
|
-
[/(bu)s$/i, '\1ses'],
|
|
39
|
-
[/(alias|status)$/i, '\1es'],
|
|
40
|
-
[/(octop|vir)i$/i, '\1i'],
|
|
41
|
-
[/(octop|vir|alumn)us$/i, '\1i'],
|
|
42
|
-
[/^(ax|test)is$/i, '\1es'],
|
|
43
|
-
[/s$/i, 's'],
|
|
44
|
-
[/$/, 's']
|
|
45
|
-
]
|
|
46
|
-
|
|
47
|
-
# Put plural-form to singular form transformations here
|
|
48
|
-
@singulars = [
|
|
49
|
-
[/^people$/, 'person'],
|
|
50
|
-
[/^men$/, 'man'],
|
|
51
|
-
[/^children$/, 'child'],
|
|
52
|
-
[/^sexes$/, 'sex'],
|
|
53
|
-
[/^moves$/, 'move'],
|
|
54
|
-
[/^kine$/, 'cow'],
|
|
55
|
-
[/^zombies$/, 'zombie'],
|
|
56
|
-
[/(database)s$/i, '\1'],
|
|
57
|
-
[/(quiz)zes$/i, '\1'],
|
|
58
|
-
[/(matr)ices$/i, '\1ix'],
|
|
59
|
-
[/(vert|ind)ices$/i, '\1ex'],
|
|
60
|
-
[/^(ox)en/i, '\1'],
|
|
61
|
-
[/(alias|status)(es)?$/i, '\1'],
|
|
62
|
-
[/(octop|vir|alumn)(us|i)$/i, '\1us'],
|
|
63
|
-
[/^(a)x[ie]s$/i, '\1xis'],
|
|
64
|
-
[/(cris|test)(is|es)$/i, '\1is'],
|
|
65
|
-
[/(shoe)s$/i, '\1'],
|
|
66
|
-
[/(o)es$/i, '\1'],
|
|
67
|
-
[/(bus)(es)?$/i, '\1'],
|
|
68
|
-
[/^(m|l)ice$/i, '\1ouse'],
|
|
69
|
-
[/(x|ch|ss|sh)es$/i, '\1'],
|
|
70
|
-
[/(m)ovies$/i, '\1ovie'],
|
|
71
|
-
[/(s)eries$/i, '\1eries'],
|
|
72
|
-
[/([^aeiouy]|qu)ies$/i, '\1y'],
|
|
73
|
-
[/([lr])ves$/i, '\1f'],
|
|
74
|
-
[/(tive)s$/i, '\1'],
|
|
75
|
-
[/(hive)s$/i, '\1'],
|
|
76
|
-
[/([^f])ves$/i, '\1fe'],
|
|
77
|
-
[/(^analy)(sis|ses)$/i, '\1sis'],
|
|
78
|
-
[/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i, '\1sis'],
|
|
79
|
-
[/([ti])a$/i, '\1um'],
|
|
80
|
-
[/(n)ews$/i, '\1ews'],
|
|
81
|
-
[/(ss)$/i, '\1'],
|
|
82
|
-
[/s$/i, '']
|
|
83
|
-
]
|
|
84
|
-
|
|
85
|
-
@irregulars = [
|
|
86
|
-
]
|
|
87
|
-
|
|
88
|
-
@uncountables = [
|
|
89
|
-
'equipment',
|
|
90
|
-
'information',
|
|
91
|
-
'rice',
|
|
92
|
-
'money',
|
|
93
|
-
'species',
|
|
94
|
-
'series',
|
|
95
|
-
'fish',
|
|
96
|
-
'sheep',
|
|
97
|
-
'jeans',
|
|
98
|
-
'police'
|
|
99
|
-
]
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
attr_reader :plurals, :singulars, :uncountables, :irregulars
|
|
103
|
-
|
|
104
|
-
def self.inflections
|
|
105
|
-
if block_given?
|
|
106
|
-
yield Inflector.instance
|
|
107
|
-
else
|
|
108
|
-
Inflector.instance
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def uncountable(word)
|
|
113
|
-
@uncountables << word
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def singular(rule, replacement)
|
|
117
|
-
@singulars << [rule, replacement]
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def plural(rule, replacement)
|
|
121
|
-
@plurals << [rule, replacement]
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def irregular(rule, replacement)
|
|
125
|
-
@irregulars << [rule, replacement]
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
def uncountable?(word)
|
|
129
|
-
return word if @uncountables.include?(word.downcase)
|
|
130
|
-
false
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
def inflect(word, direction) #nodoc
|
|
134
|
-
return word if uncountable?(word)
|
|
135
|
-
|
|
136
|
-
subject = word.dup
|
|
137
|
-
|
|
138
|
-
@irregulars.each do |rule|
|
|
139
|
-
return subject if subject.gsub!(rule.first, rule.last)
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
sense_group = direction == :singularize ? @singulars : @plurals
|
|
143
|
-
sense_group.each do |rule|
|
|
144
|
-
return subject if subject.gsub!(rule.first, rule.last)
|
|
145
|
-
end
|
|
146
|
-
subject
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
def singularize(word)
|
|
150
|
-
inflect word, :singularize
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
def pluralize(word)
|
|
154
|
-
inflect word, :pluralize
|
|
155
|
-
end
|
|
156
|
-
end
|
|
1
|
+
require 'motion-require'
|
|
2
|
+
|
|
3
|
+
files = [
|
|
4
|
+
"inflector/inflections",
|
|
5
|
+
"inflector/methods",
|
|
6
|
+
"inflections",
|
|
7
|
+
"core_ext/string/inflections",
|
|
8
|
+
|
|
9
|
+
"core_ext/array/prepend_and_append"
|
|
10
|
+
].map { |file| File.expand_path(File.join(File.dirname(__FILE__), "/../../motion", "#{file}.rb")) }
|
|
11
|
+
|
|
12
|
+
Motion::Require.all(files)
|
data/lib/motion-support.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
require
|
|
2
|
-
|
|
3
|
-
Dir.glob(File.
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
require 'motion-require'
|
|
2
|
+
|
|
3
|
+
Motion::Require.all(Dir.glob(File.expand_path('../../motion/**/*.rb', __FILE__)))
|
|
4
|
+
|
|
5
|
+
at_exit { puts "\nWARNING: Automatic dependency detection does not work with motion-support. Turn it off in your Rakefile:\n\n app.detect_dependencies = false\n\n" if Motion::Project::App.config.detect_dependencies }
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# This is a very small part of the CGI class, borrowed from the Rubinius sources
|
|
2
|
+
class CGI
|
|
3
|
+
@@accept_charset="UTF-8" unless defined?(@@accept_charset)
|
|
4
|
+
# URL-encode a string.
|
|
5
|
+
# url_encoded_string = CGI::escape("'Stop!' said Fred")
|
|
6
|
+
# # => "%27Stop%21%27+said+Fred"
|
|
7
|
+
def CGI::escape(string)
|
|
8
|
+
string.gsub(/([^ a-zA-Z0-9_.-]+)/) do
|
|
9
|
+
'%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
|
|
10
|
+
end.tr(' ', '+')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# URL-decode a string with encoding(optional).
|
|
14
|
+
# string = CGI::unescape("%27Stop%21%27+said+Fred")
|
|
15
|
+
# # => "'Stop!' said Fred"
|
|
16
|
+
def CGI::unescape(string,encoding=@@accept_charset)
|
|
17
|
+
str=string.tr('+', ' ').force_encoding(Encoding::ASCII_8BIT).gsub(/((?:%[0-9a-fA-F]{2})+)/) do
|
|
18
|
+
[$1.delete('%')].pack('H*')
|
|
19
|
+
end.force_encoding(encoding)
|
|
20
|
+
str.valid_encoding? ? str : str.force_encoding(string.encoding)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
class Date
|
|
2
|
+
def self.gregorian_leap?(year)
|
|
3
|
+
if year % 400 == 0
|
|
4
|
+
true
|
|
5
|
+
elsif year % 100 == 0 then
|
|
6
|
+
false
|
|
7
|
+
elsif year % 4 == 0 then
|
|
8
|
+
true
|
|
9
|
+
else
|
|
10
|
+
false
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize(year = nil, month = nil, day = nil)
|
|
15
|
+
if year && month && day
|
|
16
|
+
@value = Time.utc(year, month, day)
|
|
17
|
+
else
|
|
18
|
+
@value = Time.now
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.today
|
|
23
|
+
new
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_s
|
|
27
|
+
"#{year}-#{month}-#{day}"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def ==(other)
|
|
31
|
+
year == other.year &&
|
|
32
|
+
month == other.month &&
|
|
33
|
+
day == other.day
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def +(other)
|
|
37
|
+
val = @value + other * 3600 * 24
|
|
38
|
+
Date.new(val.year, val.month, val.day)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def -(other)
|
|
42
|
+
if other.is_a?(Date)
|
|
43
|
+
(@value - other.instance_variable_get(:@value)) / (3600 * 24)
|
|
44
|
+
elsif other.is_a?(Time)
|
|
45
|
+
(@value - other)
|
|
46
|
+
else
|
|
47
|
+
self + (-other)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def >>(months)
|
|
52
|
+
new_year = year + (self.month + months - 1) / 12
|
|
53
|
+
new_month = (self.month + months) % 12
|
|
54
|
+
new_month = new_month == 0 ? 12 : new_month
|
|
55
|
+
new_day = [day, Time.days_in_month(new_month, new_year)].min
|
|
56
|
+
|
|
57
|
+
Date.new(new_year, new_month, new_day)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def <<(months)
|
|
61
|
+
return self >> -months
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
[:year, :month, :day, :wday, :<, :<=, :>, :>=, :"<=>", :strftime].each do |method|
|
|
65
|
+
define_method method do |*args|
|
|
66
|
+
@value.send(method, *args)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def to_date
|
|
71
|
+
self
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def to_time
|
|
75
|
+
@value
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class Time
|
|
2
|
+
def to_date
|
|
3
|
+
Date.new(year, month, day)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def to_time
|
|
7
|
+
self
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def ==(other)
|
|
11
|
+
other &&
|
|
12
|
+
year == other.year &&
|
|
13
|
+
month == other.month &&
|
|
14
|
+
day == other.day &&
|
|
15
|
+
hour == other.hour &&
|
|
16
|
+
min == other.min &&
|
|
17
|
+
sec == other.sec
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
class Array
|
|
2
|
+
# Returns the tail of the array from +position+.
|
|
3
|
+
#
|
|
4
|
+
# %w( a b c d ).from(0) # => ["a", "b", "c", "d"]
|
|
5
|
+
# %w( a b c d ).from(2) # => ["c", "d"]
|
|
6
|
+
# %w( a b c d ).from(10) # => []
|
|
7
|
+
# %w().from(0) # => []
|
|
8
|
+
def from(position)
|
|
9
|
+
self[position, length] || []
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Returns the beginning of the array up to +position+.
|
|
13
|
+
#
|
|
14
|
+
# %w( a b c d ).to(0) # => ["a"]
|
|
15
|
+
# %w( a b c d ).to(2) # => ["a", "b", "c"]
|
|
16
|
+
# %w( a b c d ).to(10) # => ["a", "b", "c", "d"]
|
|
17
|
+
# %w().to(0) # => []
|
|
18
|
+
def to(position)
|
|
19
|
+
first position + 1
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Equal to <tt>self[1]</tt>.
|
|
23
|
+
#
|
|
24
|
+
# %w( a b c d e ).second # => "b"
|
|
25
|
+
def second
|
|
26
|
+
self[1]
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
class Array
|
|
2
|
+
# Converts the array to a comma-separated sentence where the last element is
|
|
3
|
+
# joined by the connector word.
|
|
4
|
+
#
|
|
5
|
+
# You can pass the following options to change the default behavior. If you
|
|
6
|
+
# pass an option key that doesn't exist in the list below, it will raise an
|
|
7
|
+
# <tt>ArgumentError</tt>.
|
|
8
|
+
#
|
|
9
|
+
# Options:
|
|
10
|
+
#
|
|
11
|
+
# * <tt>:words_connector</tt> - The sign or word used to join the elements
|
|
12
|
+
# in arrays with two or more elements (default: ", ").
|
|
13
|
+
# * <tt>:two_words_connector</tt> - The sign or word used to join the elements
|
|
14
|
+
# in arrays with two elements (default: " and ").
|
|
15
|
+
# * <tt>:last_word_connector</tt> - The sign or word used to join the last element
|
|
16
|
+
# in arrays with three or more elements (default: ", and ").
|
|
17
|
+
#
|
|
18
|
+
# [].to_sentence # => ""
|
|
19
|
+
# ['one'].to_sentence # => "one"
|
|
20
|
+
# ['one', 'two'].to_sentence # => "one and two"
|
|
21
|
+
# ['one', 'two', 'three'].to_sentence # => "one, two, and three"
|
|
22
|
+
#
|
|
23
|
+
# ['one', 'two'].to_sentence(passing: 'invalid option')
|
|
24
|
+
# # => ArgumentError: Unknown key :passing
|
|
25
|
+
#
|
|
26
|
+
# ['one', 'two'].to_sentence(two_words_connector: '-')
|
|
27
|
+
# # => "one-two"
|
|
28
|
+
#
|
|
29
|
+
# ['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ')
|
|
30
|
+
# # => "one or two or at least three"
|
|
31
|
+
def to_sentence(options = {})
|
|
32
|
+
options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector)
|
|
33
|
+
|
|
34
|
+
default_connectors = {
|
|
35
|
+
:words_connector => ', ',
|
|
36
|
+
:two_words_connector => ' and ',
|
|
37
|
+
:last_word_connector => ', and '
|
|
38
|
+
}
|
|
39
|
+
options = default_connectors.merge!(options)
|
|
40
|
+
|
|
41
|
+
case length
|
|
42
|
+
when 0
|
|
43
|
+
''
|
|
44
|
+
when 1
|
|
45
|
+
self[0].to_s.dup
|
|
46
|
+
when 2
|
|
47
|
+
"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
|
|
48
|
+
else
|
|
49
|
+
"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Converts a collection of elements into a formatted string by calling
|
|
54
|
+
# <tt>to_s</tt> on all elements and joining them. Having this model:
|
|
55
|
+
#
|
|
56
|
+
# class Blog < ActiveRecord::Base
|
|
57
|
+
# def to_s
|
|
58
|
+
# title
|
|
59
|
+
# end
|
|
60
|
+
# end
|
|
61
|
+
#
|
|
62
|
+
# Blog.all.map(&:title) #=> ["First Post", "Second Post", "Third post"]
|
|
63
|
+
#
|
|
64
|
+
# <tt>to_formatted_s</tt> shows us:
|
|
65
|
+
#
|
|
66
|
+
# Blog.all.to_formatted_s # => "First PostSecond PostThird Post"
|
|
67
|
+
#
|
|
68
|
+
# Adding in the <tt>:db</tt> argument as the format yields a comma separated
|
|
69
|
+
# id list:
|
|
70
|
+
#
|
|
71
|
+
# Blog.all.to_formatted_s(:db) # => "1,2,3"
|
|
72
|
+
def to_formatted_s(format = :default)
|
|
73
|
+
case format
|
|
74
|
+
when :db
|
|
75
|
+
if empty?
|
|
76
|
+
'null'
|
|
77
|
+
else
|
|
78
|
+
collect { |element| element.id }.join(',')
|
|
79
|
+
end
|
|
80
|
+
else
|
|
81
|
+
to_default_s
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
alias_method :to_default_s, :to_s
|
|
85
|
+
alias_method :to_s, :to_formatted_s
|
|
86
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
class Array
|
|
2
|
+
# Splits or iterates over the array in groups of size +number+,
|
|
3
|
+
# padding any remaining slots with +fill_with+ unless it is +false+.
|
|
4
|
+
#
|
|
5
|
+
# %w(1 2 3 4 5 6 7 8 9 10).in_groups_of(3) {|group| p group}
|
|
6
|
+
# ["1", "2", "3"]
|
|
7
|
+
# ["4", "5", "6"]
|
|
8
|
+
# ["7", "8", "9"]
|
|
9
|
+
# ["10", nil, nil]
|
|
10
|
+
#
|
|
11
|
+
# %w(1 2 3 4 5).in_groups_of(2, ' ') {|group| p group}
|
|
12
|
+
# ["1", "2"]
|
|
13
|
+
# ["3", "4"]
|
|
14
|
+
# ["5", " "]
|
|
15
|
+
#
|
|
16
|
+
# %w(1 2 3 4 5).in_groups_of(2, false) {|group| p group}
|
|
17
|
+
# ["1", "2"]
|
|
18
|
+
# ["3", "4"]
|
|
19
|
+
# ["5"]
|
|
20
|
+
def in_groups_of(number, fill_with = nil)
|
|
21
|
+
if fill_with == false
|
|
22
|
+
collection = self
|
|
23
|
+
else
|
|
24
|
+
# size % number gives how many extra we have;
|
|
25
|
+
# subtracting from number gives how many to add;
|
|
26
|
+
# modulo number ensures we don't add group of just fill.
|
|
27
|
+
padding = (number - size % number) % number
|
|
28
|
+
collection = dup.concat([fill_with] * padding)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
if block_given?
|
|
32
|
+
collection.each_slice(number) { |slice| yield(slice) }
|
|
33
|
+
else
|
|
34
|
+
groups = []
|
|
35
|
+
collection.each_slice(number) { |group| groups << group }
|
|
36
|
+
groups
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Splits or iterates over the array in +number+ of groups, padding any
|
|
41
|
+
# remaining slots with +fill_with+ unless it is +false+.
|
|
42
|
+
#
|
|
43
|
+
# %w(1 2 3 4 5 6 7 8 9 10).in_groups(3) {|group| p group}
|
|
44
|
+
# ["1", "2", "3", "4"]
|
|
45
|
+
# ["5", "6", "7", nil]
|
|
46
|
+
# ["8", "9", "10", nil]
|
|
47
|
+
#
|
|
48
|
+
# %w(1 2 3 4 5 6 7 8 9 10).in_groups(3, ' ') {|group| p group}
|
|
49
|
+
# ["1", "2", "3", "4"]
|
|
50
|
+
# ["5", "6", "7", " "]
|
|
51
|
+
# ["8", "9", "10", " "]
|
|
52
|
+
#
|
|
53
|
+
# %w(1 2 3 4 5 6 7).in_groups(3, false) {|group| p group}
|
|
54
|
+
# ["1", "2", "3"]
|
|
55
|
+
# ["4", "5"]
|
|
56
|
+
# ["6", "7"]
|
|
57
|
+
def in_groups(number, fill_with = nil)
|
|
58
|
+
# size / number gives minor group size;
|
|
59
|
+
# size % number gives how many objects need extra accommodation;
|
|
60
|
+
# each group hold either division or division + 1 items.
|
|
61
|
+
division = size.div number
|
|
62
|
+
modulo = size % number
|
|
63
|
+
|
|
64
|
+
# create a new array avoiding dup
|
|
65
|
+
groups = []
|
|
66
|
+
start = 0
|
|
67
|
+
|
|
68
|
+
number.times do |index|
|
|
69
|
+
length = division + (modulo > 0 && modulo > index ? 1 : 0)
|
|
70
|
+
groups << last_group = slice(start, length)
|
|
71
|
+
last_group << fill_with if fill_with != false &&
|
|
72
|
+
modulo > 0 && length == division
|
|
73
|
+
start += length
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
if block_given?
|
|
77
|
+
groups.each { |g| yield(g) }
|
|
78
|
+
else
|
|
79
|
+
groups
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Divides the array into one or more subarrays based on a delimiting +value+
|
|
84
|
+
# or the result of an optional block.
|
|
85
|
+
#
|
|
86
|
+
# [1, 2, 3, 4, 5].split(3) # => [[1, 2], [4, 5]]
|
|
87
|
+
# (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
|
|
88
|
+
def split(value = nil, &block)
|
|
89
|
+
inject([[]]) do |results, element|
|
|
90
|
+
if block && block.call(element) || value == element
|
|
91
|
+
results << []
|
|
92
|
+
else
|
|
93
|
+
results.last << element
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
results
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
class Array
|
|
2
|
+
# Wraps its argument in an array unless it is already an array (or array-like).
|
|
3
|
+
#
|
|
4
|
+
# Specifically:
|
|
5
|
+
#
|
|
6
|
+
# * If the argument is +nil+ an empty list is returned.
|
|
7
|
+
# * Otherwise, if the argument responds to +to_ary+ it is invoked, and its result returned.
|
|
8
|
+
# * Otherwise, returns an array with the argument as its single element.
|
|
9
|
+
#
|
|
10
|
+
# Array.wrap(nil) # => []
|
|
11
|
+
# Array.wrap([1, 2, 3]) # => [1, 2, 3]
|
|
12
|
+
# Array.wrap(0) # => [0]
|
|
13
|
+
#
|
|
14
|
+
# This method is similar in purpose to <tt>Kernel#Array</tt>, but there are some differences:
|
|
15
|
+
#
|
|
16
|
+
# * If the argument responds to +to_ary+ the method is invoked. <tt>Kernel#Array</tt>
|
|
17
|
+
# moves on to try +to_a+ if the returned value is +nil+, but <tt>Array.wrap</tt> returns
|
|
18
|
+
# such a +nil+ right away.
|
|
19
|
+
# * If the returned value from +to_ary+ is neither +nil+ nor an +Array+ object, <tt>Kernel#Array</tt>
|
|
20
|
+
# raises an exception, while <tt>Array.wrap</tt> does not, it just returns the value.
|
|
21
|
+
# * It does not call +to_a+ on the argument, though special-cases +nil+ to return an empty array.
|
|
22
|
+
#
|
|
23
|
+
# The last point is particularly worth comparing for some enumerables:
|
|
24
|
+
#
|
|
25
|
+
# Array(foo: :bar) # => [[:foo, :bar]]
|
|
26
|
+
# Array.wrap(foo: :bar) # => [{:foo=>:bar}]
|
|
27
|
+
#
|
|
28
|
+
# There's also a related idiom that uses the splat operator:
|
|
29
|
+
#
|
|
30
|
+
# [*object]
|
|
31
|
+
#
|
|
32
|
+
# which for +nil+ returns <tt>[]</tt>, and calls to <tt>Array(object)</tt> otherwise.
|
|
33
|
+
#
|
|
34
|
+
# Thus, in this case the behavior may be different for +nil+, and the differences with
|
|
35
|
+
# <tt>Kernel#Array</tt> explained above apply to the rest of <tt>object</tt>s.
|
|
36
|
+
def self.wrap(object)
|
|
37
|
+
if object.nil?
|
|
38
|
+
[]
|
|
39
|
+
elsif object.respond_to?(:to_ary)
|
|
40
|
+
object.to_ary || [object]
|
|
41
|
+
else
|
|
42
|
+
[object]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|