active_object 1.0.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.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +14 -0
- data/.rspec +4 -0
- data/.travis.yml +13 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +1361 -0
- data/Rakefile +1 -0
- data/active_object.gemspec +25 -0
- data/lib/active_object.rb +9 -0
- data/lib/active_object/array.rb +118 -0
- data/lib/active_object/enumerable.rb +172 -0
- data/lib/active_object/hash.rb +203 -0
- data/lib/active_object/integer.rb +7 -0
- data/lib/active_object/numeric.rb +523 -0
- data/lib/active_object/object.rb +41 -0
- data/lib/active_object/string.rb +311 -0
- data/lib/active_object/time.rb +150 -0
- data/lib/active_object/version.rb +3 -0
- data/spec/lib/array_spec.rb +125 -0
- data/spec/lib/enumerable_spec.rb +326 -0
- data/spec/lib/hash_spec.rb +191 -0
- data/spec/lib/integer_spec.rb +11 -0
- data/spec/lib/numeric_spec.rb +604 -0
- data/spec/lib/object_spec.rb +85 -0
- data/spec/lib/string_spec.rb +459 -0
- data/spec/lib/time_spec.rb +455 -0
- data/spec/spec_helper.rb +4 -0
- metadata +137 -0
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'active_object/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "active_object"
|
8
|
+
spec.version = ActiveObject::VERSION
|
9
|
+
spec.authors = ["Juan Gomez"]
|
10
|
+
spec.email = ["j.gomez@drexed.com"]
|
11
|
+
spec.summary = %q{Commonly used ruby object helpers.}
|
12
|
+
spec.description = %q{Class extensions of commonly used ruby object helpers.}
|
13
|
+
spec.homepage = "https://github.com/drexed/active_object"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler"
|
22
|
+
spec.add_development_dependency "coveralls"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "rspec"
|
25
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'active_object/version'
|
2
|
+
require 'active_object/array'
|
3
|
+
require 'active_object/enumerable'
|
4
|
+
require 'active_object/hash'
|
5
|
+
require 'active_object/integer'
|
6
|
+
require 'active_object/numeric'
|
7
|
+
require 'active_object/object'
|
8
|
+
require 'active_object/string'
|
9
|
+
require 'active_object/time'
|
@@ -0,0 +1,118 @@
|
|
1
|
+
class Array
|
2
|
+
|
3
|
+
def delete_first
|
4
|
+
self[1..-1]
|
5
|
+
end
|
6
|
+
|
7
|
+
def delete_last
|
8
|
+
self[0...-1]
|
9
|
+
end
|
10
|
+
|
11
|
+
unless method_defined?(:from)
|
12
|
+
def from(position)
|
13
|
+
self[position, size] || []
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def groups(number)
|
18
|
+
return([]) if number <= 0
|
19
|
+
n, r = size.divmod(number)
|
20
|
+
collection = (0..(n - 1)).collect { |i| self[(i * number), number] }
|
21
|
+
r > 0 ? collection << self[-r, r] : collection
|
22
|
+
end
|
23
|
+
|
24
|
+
unless method_defined?(:in_groups)
|
25
|
+
def in_groups(number, fill_with=nil)
|
26
|
+
collection_size = size
|
27
|
+
division = collection_size.div(number)
|
28
|
+
modulo = collection_size % number
|
29
|
+
|
30
|
+
collection = []
|
31
|
+
start = 0
|
32
|
+
number.times do |i|
|
33
|
+
grouping = division + (modulo > 0 && modulo > i ? 1 : 0)
|
34
|
+
collection << last_group = slice(start, grouping)
|
35
|
+
last_group << fill_with if fill_with != false && modulo > 0 && grouping == division
|
36
|
+
start += grouping
|
37
|
+
end
|
38
|
+
|
39
|
+
block_given? ? collection.each { |g| yield(g) } : collection
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
unless method_defined?(:in_groups_of)
|
44
|
+
def in_groups_of(number, fill_with=nil)
|
45
|
+
if number.to_i <= 0
|
46
|
+
raise ArgumentError,
|
47
|
+
"Group size must be a positive integer, was #{number.inspect}"
|
48
|
+
end
|
49
|
+
|
50
|
+
if fill_with == false
|
51
|
+
collection = self
|
52
|
+
else
|
53
|
+
padding = (number - size % number) % number
|
54
|
+
collection = dup.concat(Array.new(padding, fill_with))
|
55
|
+
end
|
56
|
+
|
57
|
+
block_given? ? collection.each_slice(number) { |slice| yield(slice) } : collection.each_slice(number).to_a
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
unless method_defined?(:split)
|
62
|
+
def split(number=nil)
|
63
|
+
if block_given?
|
64
|
+
inject([[]]) do |results, element|
|
65
|
+
yield(element) ? results << [] : results.last << element
|
66
|
+
results
|
67
|
+
end
|
68
|
+
else
|
69
|
+
results, arr = [[]], dup
|
70
|
+
until arr.empty?
|
71
|
+
if (idx = arr.index(number))
|
72
|
+
results.last.concat(arr.shift(idx))
|
73
|
+
arr.shift
|
74
|
+
results << []
|
75
|
+
else
|
76
|
+
results.last.concat(arr.shift(arr.size))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
results
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def strip
|
85
|
+
reject { |v| v.blank? }
|
86
|
+
end
|
87
|
+
|
88
|
+
unless method_defined?(:to)
|
89
|
+
def to(position)
|
90
|
+
position >= 0 ? first(position + 1) : self[0..position]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
unless method_defined?(:to_sentence)
|
95
|
+
def to_sentence(options={})
|
96
|
+
options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector)
|
97
|
+
|
98
|
+
default_connectors = {
|
99
|
+
words_connector: ', ',
|
100
|
+
two_words_connector: ' and ',
|
101
|
+
last_word_connector: ', and '
|
102
|
+
}
|
103
|
+
options = default_connectors.merge!(options)
|
104
|
+
|
105
|
+
case size
|
106
|
+
when 0
|
107
|
+
''
|
108
|
+
when 1
|
109
|
+
self[0].to_s.dup
|
110
|
+
when 2
|
111
|
+
"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
|
112
|
+
else
|
113
|
+
"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
module Enumerable
|
2
|
+
|
3
|
+
def difference(identity=0, &block)
|
4
|
+
if block_given?
|
5
|
+
map(&block).difference(identity)
|
6
|
+
else
|
7
|
+
inject { |d,v| d - v } || identity
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def divisible(identity=0, &block)
|
12
|
+
if block_given?
|
13
|
+
map(&block).divisible(identity)
|
14
|
+
else
|
15
|
+
inject { |d,v| d / v } || identity
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def drop_last(n)
|
20
|
+
collection_size = to_a.size
|
21
|
+
return(self) if n > collection_size
|
22
|
+
self[0...(collection_size - n)]
|
23
|
+
end
|
24
|
+
|
25
|
+
def drop_last_if
|
26
|
+
return(to_enum(:drop_last_if)) unless block_given?
|
27
|
+
|
28
|
+
result = []
|
29
|
+
dropping = true
|
30
|
+
reverse_each do |value|
|
31
|
+
result.unshift(value) unless dropping &&= yield(value)
|
32
|
+
end
|
33
|
+
result
|
34
|
+
end
|
35
|
+
|
36
|
+
def exactly?(n)
|
37
|
+
found_count = 0
|
38
|
+
block_given? ? each { |*o| found_count += 1 if yield(*o) } : each { |o| found_count += 1 if o }
|
39
|
+
(found_count > n) ? false : n == found_count
|
40
|
+
end
|
41
|
+
|
42
|
+
unless method_defined?(:exclude?)
|
43
|
+
def exclude?(object)
|
44
|
+
!include?(object)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def exponential(identity=0, &block)
|
49
|
+
if block_given?
|
50
|
+
map(&block).exponential(identity)
|
51
|
+
else
|
52
|
+
inject { |d,v| d ** v } || identity
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def frequencies
|
57
|
+
each_with_object(Hash.new(0)) { |e, a| a[e] += 1 }
|
58
|
+
end
|
59
|
+
|
60
|
+
unless method_defined?(:many?)
|
61
|
+
def many?
|
62
|
+
found_count = 0
|
63
|
+
if block_given?
|
64
|
+
any? do |v|
|
65
|
+
found_count += 1 if yield v
|
66
|
+
found_count > 1
|
67
|
+
end
|
68
|
+
else
|
69
|
+
any? { (found_count += 1) > 1 }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def max(identity=0)
|
75
|
+
size > 0 ? sort.last : identity
|
76
|
+
end
|
77
|
+
|
78
|
+
def min(identity=0)
|
79
|
+
size > 0 ? sort.first : identity
|
80
|
+
end
|
81
|
+
|
82
|
+
def mean(identity=0)
|
83
|
+
return(identity) unless size > 0
|
84
|
+
collection_size = size
|
85
|
+
sum / collection_size.to_f
|
86
|
+
end
|
87
|
+
|
88
|
+
def median(identity=0)
|
89
|
+
collection_size = size
|
90
|
+
collection_sorted = sort
|
91
|
+
|
92
|
+
return(identity) unless collection_size > 0
|
93
|
+
|
94
|
+
if (collection_size % 2).zero?
|
95
|
+
(collection_sorted[(collection_size / 2.0) -1.0] + collection_sorted[collection_size / 2.0]) / 2.0
|
96
|
+
else
|
97
|
+
collection_sorted[collection_size / 2.0]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def mode(identity=0)
|
102
|
+
return(identity) unless size > 0
|
103
|
+
|
104
|
+
frequency_distribution = inject(Hash.new(0)) { |h,v| h[v] += 1; h }
|
105
|
+
frequency_top_two = frequency_distribution.sort { |k,v| v[1] <=> k[1] }.take(2)
|
106
|
+
|
107
|
+
if frequency_top_two.size == 1
|
108
|
+
frequency_top_two.first.first
|
109
|
+
elsif frequency_top_two.first.last == frequency_top_two.last.last
|
110
|
+
nil
|
111
|
+
else
|
112
|
+
frequency_top_two.first.first
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def multiple(identity=0, &block)
|
117
|
+
if block_given?
|
118
|
+
map(&block).multiple(identity)
|
119
|
+
else
|
120
|
+
inject { |d,v| d * v } || identity
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def range(identity=0)
|
125
|
+
return(identity) unless size > 0
|
126
|
+
collection_sorted = sort
|
127
|
+
collection_sorted.last - collection_sorted.first
|
128
|
+
end
|
129
|
+
|
130
|
+
def several?
|
131
|
+
found_count = 0
|
132
|
+
block_given? ? each { |*o| found_count += 1 if yield(*o) } : each { |o| found_count += 1 if o }
|
133
|
+
(found_count > 1) ? true : false
|
134
|
+
end
|
135
|
+
|
136
|
+
def standard_deviation(identity=0)
|
137
|
+
return(identity) if size < 2
|
138
|
+
Math.sqrt(variance)
|
139
|
+
end
|
140
|
+
|
141
|
+
unless method_defined?(:sum)
|
142
|
+
def sum(identity=0, &block)
|
143
|
+
if block_given?
|
144
|
+
map(&block).sum(identity)
|
145
|
+
else
|
146
|
+
inject { |s,v| s + v } || identity
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def take_last(n)
|
152
|
+
collection_size = to_a.size
|
153
|
+
return(self) if n > collection_size
|
154
|
+
self[(collection_size - n)..-1]
|
155
|
+
end
|
156
|
+
|
157
|
+
def take_last_if
|
158
|
+
return(to_enum(:take_last_if)) unless block_given?
|
159
|
+
|
160
|
+
result = []
|
161
|
+
reverse_each { |e| yield(e) ? result.unshift(e) : break }
|
162
|
+
result
|
163
|
+
end
|
164
|
+
|
165
|
+
def variance(identity=0)
|
166
|
+
collection_size = size
|
167
|
+
return(identity) if collection_size <= 1
|
168
|
+
sum = inject(0.0) { |s,v| s + (v - mean) ** 2.0 }
|
169
|
+
sum / (collection_size.to_f - 1.0)
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
class Hash
|
2
|
+
|
3
|
+
unless method_defined?(:assert_valid_keys)
|
4
|
+
def assert_valid_keys(*valid_keys)
|
5
|
+
valid_keys.flatten!
|
6
|
+
each_key do |k|
|
7
|
+
unless valid_keys.include?(k)
|
8
|
+
raise ArgumentError, "Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
unless method_defined?(:compact)
|
15
|
+
def compact
|
16
|
+
select { |k,v| !v.nil? }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
unless method_defined?(:compact!)
|
21
|
+
def compact!
|
22
|
+
reject! { |k,v| v.nil? }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
unless method_defined?(:deep_merge)
|
27
|
+
def deep_merge(other_hash, &block)
|
28
|
+
dup.deep_merge!(other_hash, &block)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
unless method_defined?(:deep_merge!)
|
33
|
+
def deep_merge!(other_hash, &block)
|
34
|
+
other_hash.each_pair do |current_key, other_value|
|
35
|
+
this_value = self[current_key]
|
36
|
+
|
37
|
+
self[current_key] = if this_value.is_a?(Hash) && other_value.is_a?(Hash)
|
38
|
+
this_value.deep_merge(other_value, &block)
|
39
|
+
else
|
40
|
+
block_given? && key?(current_key) ? block.call(current_key, this_value, other_value) : other_value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
self
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
unless method_defined?(:except)
|
48
|
+
def except(*keys)
|
49
|
+
dup.except!(*keys)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
unless method_defined?(:except!)
|
54
|
+
def except!(*keys)
|
55
|
+
keys.each { |k| delete(k) }
|
56
|
+
self
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def nillify
|
61
|
+
dup.nillify!
|
62
|
+
end
|
63
|
+
|
64
|
+
def nillify!
|
65
|
+
each do |k, v|
|
66
|
+
if !v.nil? && ((v.respond_to?(:blank?) && v.blank?) || (v.respond_to?(:to_s) && v.to_s.blank?))
|
67
|
+
self[k] = nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
unless method_defined?(:only)
|
73
|
+
def only(*keys)
|
74
|
+
dup.only!(*keys)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
unless method_defined?(:only!)
|
79
|
+
def only!(*args)
|
80
|
+
hash = {}
|
81
|
+
args.each {|k| hash[k] = self[k] if self.has_key?(k) }
|
82
|
+
hash
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def rename_keys(*args)
|
87
|
+
dup.rename_keys!(*args)
|
88
|
+
end
|
89
|
+
|
90
|
+
def rename_keys!(*args)
|
91
|
+
keys = Hash[*args.flatten]
|
92
|
+
keys.each { |k, v| self[v] = delete(k) if self[k] }
|
93
|
+
self
|
94
|
+
end
|
95
|
+
|
96
|
+
unless method_defined?(:reverse_merge)
|
97
|
+
def reverse_merge(other_hash)
|
98
|
+
other_hash.merge(self)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
unless method_defined?(:reverse_merge!)
|
103
|
+
def reverse_merge!(other_hash)
|
104
|
+
merge!(other_hash) { |k,l,r| l }
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
unless method_defined?(:slice)
|
109
|
+
def slice(*keys)
|
110
|
+
keys.each_with_object(self.class.new) { |k, h| h[k] = self[k] if has_key?(k) }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
unless method_defined?(:slice!)
|
115
|
+
def slice!(*keys)
|
116
|
+
omit = slice(*self.keys - keys)
|
117
|
+
hash = slice(*keys)
|
118
|
+
|
119
|
+
hash.default = default
|
120
|
+
hash.default_proc = default_proc if default_proc
|
121
|
+
|
122
|
+
replace(hash)
|
123
|
+
omit
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
unless method_defined?(:stringify_keys)
|
128
|
+
def stringify_keys
|
129
|
+
dup.stringify_keys!
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
unless method_defined?(:stringify_keys!)
|
134
|
+
def stringify_keys!
|
135
|
+
inject({}) do |options,(k,v)|
|
136
|
+
options[k.to_s] = v
|
137
|
+
options
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def strip
|
143
|
+
select { |k,v| !v.blank? }
|
144
|
+
end
|
145
|
+
|
146
|
+
def strip!
|
147
|
+
reject! { |k,v| v.blank? }
|
148
|
+
end
|
149
|
+
|
150
|
+
unless method_defined?(:symbolize_keys)
|
151
|
+
def symbolize_keys
|
152
|
+
dup.symbolize_keys!
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
unless method_defined?(:symbolize_keys!)
|
157
|
+
def symbolize_keys!
|
158
|
+
inject({}) do |options, (k,v)|
|
159
|
+
options[(k.to_sym rescue k) || k] = v
|
160
|
+
options
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def symbolize_and_underscore_keys
|
166
|
+
dup.symbolize_and_underscore_keys!
|
167
|
+
end
|
168
|
+
|
169
|
+
def symbolize_and_underscore_keys!
|
170
|
+
inject({}) do |options, (k,v)|
|
171
|
+
options[(k.to_s.gsub(" ", "_").underscore.to_sym rescue k) || k] = v
|
172
|
+
options
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
unless method_defined?(:transform_keys)
|
177
|
+
def transform_keys(&block)
|
178
|
+
dup.transform_keys!(&block)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
unless method_defined?(:transform_keys!)
|
183
|
+
def transform_keys!(&block)
|
184
|
+
return(enum_for(:transform_keys!)) unless block_given?
|
185
|
+
keys.each { |k| self[yield(k)] = delete(k) }
|
186
|
+
self
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
unless method_defined?(:transform_values)
|
191
|
+
def transform_values(&block)
|
192
|
+
dup.transform_values!(&block)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
unless method_defined?(:transform_values!)
|
197
|
+
def transform_values!(&block)
|
198
|
+
return(enum_for(:transform_values!)) unless block_given?
|
199
|
+
each { |k,v| self[k] = yield(v) }
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|