more_core_extensions 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +63 -0
- data/Rakefile +6 -0
- data/lib/more_core_extensions/all.rb +5 -0
- data/lib/more_core_extensions/core_ext/array/duplicates.rb +11 -0
- data/lib/more_core_extensions/core_ext/array/inclusions.rb +33 -0
- data/lib/more_core_extensions/core_ext/array/random.rb +19 -0
- data/lib/more_core_extensions/core_ext/array/stretch.rb +49 -0
- data/lib/more_core_extensions/core_ext/array/tableize.rb +89 -0
- data/lib/more_core_extensions/core_ext/array.rb +5 -0
- data/lib/more_core_extensions/core_ext/hash/deletes.rb +19 -0
- data/lib/more_core_extensions/core_ext/hash/nested.rb +56 -0
- data/lib/more_core_extensions/core_ext/hash.rb +2 -0
- data/lib/more_core_extensions/core_ext/string/formats.rb +41 -0
- data/lib/more_core_extensions/core_ext/string/hex_dump.rb +55 -0
- data/lib/more_core_extensions/core_ext/string.rb +2 -0
- data/lib/more_core_extensions/version.rb +3 -0
- data/lib/more_core_extensions.rb +1 -0
- data/more_core_extensions.gemspec +27 -0
- data/spec/core_ext/array/duplicates_spec.rb +11 -0
- data/spec/core_ext/array/inclusions_spec.rb +33 -0
- data/spec/core_ext/array/stretch_spec.rb +96 -0
- data/spec/core_ext/array/tableize_spec.rb +158 -0
- data/spec/core_ext/hash/deletes_spec.rb +17 -0
- data/spec/core_ext/hash/nested_spec.rb +125 -0
- data/spec/core_ext/string/formats_spec.rb +63 -0
- data/spec/core_ext/string/hex_dump_spec.rb +86 -0
- data/spec/spec_helper.rb +21 -0
- metadata +175 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Red Hat, Inc.
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# MoreCoreExtensions
|
2
|
+
|
3
|
+
MoreCoreExtensions are a set of core extensions beyond those provided by ActiveSupport.
|
4
|
+
|
5
|
+
[![Build Status](https://travis-ci.org/ManageIQ/more_core_extensions.png?branch=master)](https://travis-ci.org/ManageIQ/more_core_extensions)
|
6
|
+
[![Code Climate](https://codeclimate.com/github/ManageIQ/more_core_extensions.png)](https://codeclimate.com/github/ManageIQ/more_core_extensions)
|
7
|
+
[![Coverage Status](https://coveralls.io/repos/ManageIQ/more_core_extensions/badge.png)](https://coveralls.io/r/ManageIQ/more_core_extensions)
|
8
|
+
[![Dependency Status](https://gemnasium.com/ManageIQ/more_core_extensions.png)](https://gemnasium.com/ManageIQ/more_core_extensions)
|
9
|
+
|
10
|
+
## Extensions Provided
|
11
|
+
|
12
|
+
* Array
|
13
|
+
* duplicates
|
14
|
+
* include_any?
|
15
|
+
* include_none?
|
16
|
+
* include_all?
|
17
|
+
* random_index
|
18
|
+
* random_element
|
19
|
+
* stretch
|
20
|
+
* stretch!
|
21
|
+
* zip_stretched
|
22
|
+
* tableize
|
23
|
+
* Hash
|
24
|
+
* delete_nils
|
25
|
+
* delete_blanks
|
26
|
+
* fetch_path
|
27
|
+
* has_key_path?
|
28
|
+
* include_path?
|
29
|
+
* key_path?
|
30
|
+
* member_path?
|
31
|
+
* store_path
|
32
|
+
* delete_path
|
33
|
+
* String
|
34
|
+
* email?
|
35
|
+
* domain_name?
|
36
|
+
* ipv4?
|
37
|
+
* ipv6?
|
38
|
+
* ipaddress?
|
39
|
+
* integer?
|
40
|
+
* guid?
|
41
|
+
* hex_dump
|
42
|
+
|
43
|
+
## Installation
|
44
|
+
|
45
|
+
Add this line to your application's Gemfile:
|
46
|
+
|
47
|
+
gem 'more_core_extensions'
|
48
|
+
|
49
|
+
And then execute:
|
50
|
+
|
51
|
+
$ bundle
|
52
|
+
|
53
|
+
Or install it yourself as:
|
54
|
+
|
55
|
+
$ gem install more_core_extensions
|
56
|
+
|
57
|
+
## Contributing
|
58
|
+
|
59
|
+
1. Fork it
|
60
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
61
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
62
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
63
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
module MoreCoreExtensions::ArrayDuplicates
|
2
|
+
#
|
3
|
+
# Returns an Array of the duplicates found.
|
4
|
+
#
|
5
|
+
# [1, 2, 3, 4, 2, 4].duplicates #=> [2, 4]
|
6
|
+
def duplicates
|
7
|
+
self.inject(Hash.new(0)) { |h, v| h[v] += 1; h }.reject { |k, v| v == 1 }.keys
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
Array.send(:include, MoreCoreExtensions::ArrayDuplicates)
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module MoreCoreExtensions::ArrayInclusions
|
2
|
+
#
|
3
|
+
# Returns whether the Array contains any of the items.
|
4
|
+
#
|
5
|
+
# [1, 2, 3].include_any?(1, 2) #=> true
|
6
|
+
# [1, 2, 3].include_any?(1, 4) #=> true
|
7
|
+
# [1, 2, 3].include_any?(4, 5) #=> false
|
8
|
+
def include_any?(*items)
|
9
|
+
!(self & items).empty?
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
# Returns whether the Array contains none of the items.
|
14
|
+
#
|
15
|
+
# [1, 2, 3].include_none?(1, 2) #=> false
|
16
|
+
# [1, 2, 3].include_none?(1, 4) #=> false
|
17
|
+
# [1, 2, 3].include_none?(4, 5) #=> true
|
18
|
+
def include_none?(*items)
|
19
|
+
(self & items).empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# Returns whether the Array contains all of the items.
|
24
|
+
#
|
25
|
+
# [1, 2, 3].include_all?(1, 2) #=> true
|
26
|
+
# [1, 2, 3].include_all?(1, 4) #=> false
|
27
|
+
# [1, 2, 3].include_all?(4, 5) #=> false
|
28
|
+
def include_all?(*items)
|
29
|
+
(items - self).empty?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
Array.send(:include, MoreCoreExtensions::ArrayInclusions)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module MoreCoreExtensions::ArrayRandom
|
2
|
+
#
|
3
|
+
# Picks a valid index randomly
|
4
|
+
#
|
5
|
+
# [1, 2, 3, 4, 2, 4].random_index #=> random number between 0..5
|
6
|
+
def random_index
|
7
|
+
rand(self.size)
|
8
|
+
end
|
9
|
+
|
10
|
+
#
|
11
|
+
# Picks an element randomly
|
12
|
+
#
|
13
|
+
# [1, 2, 3, 4, 2, 4].random_element #=> any randomly selected element in Array
|
14
|
+
def random_element
|
15
|
+
self[self.random_index]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Array.send(:include, MoreCoreExtensions::ArrayRandom)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module MoreCoreExtensions::ArrayStretch
|
2
|
+
module ClassMethods
|
3
|
+
# Stretch all argument Arrays to make them the same size.
|
4
|
+
#
|
5
|
+
# Array.stretch([1, 2], [3, 4], [5, 6, 7]) #=> [[1, 2, nil], [3, 4, nil], [5, 6, 7]]
|
6
|
+
def stretch(*arys)
|
7
|
+
self.stretch!(*arys.collect { |a| a.dup })
|
8
|
+
end
|
9
|
+
|
10
|
+
# Stretch all argument Arrays to make them the same size. Modifies the arguments in place.
|
11
|
+
#
|
12
|
+
# Array.stretch!([1, 2], [3, 4], [5, 6, 7]) #=> [[1, 2, nil], [3, 4, nil], [5, 6, 7]]
|
13
|
+
def stretch!(*arys)
|
14
|
+
max_size = arys.collect { |a| a.length }.max
|
15
|
+
arys.each { |a| a[max_size - 1] = nil unless a.length == max_size }
|
16
|
+
return *arys
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Stretch receiver to be the same size as the longest argument Array.
|
21
|
+
#
|
22
|
+
# [1, 2].stretch([3, 4], [5, 6, 7]) #=> [1, 2, nil]
|
23
|
+
def stretch(*arys)
|
24
|
+
self.dup.stretch!(*arys)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Stretch receiver to be the same size as the longest argument Array. Modifies the receiver in place.
|
28
|
+
#
|
29
|
+
# [1, 2].stretch!([3, 4], [5, 6, 7]) #=> [1, 2, nil]
|
30
|
+
def stretch!(*arys)
|
31
|
+
max_size = (arys + [self]).collect { |a| a.length }.max
|
32
|
+
self[max_size - 1] = nil unless self.length == max_size
|
33
|
+
return self
|
34
|
+
end
|
35
|
+
|
36
|
+
# Zip arguments stretching the receiver if necessary. Ruby's +zip+ method
|
37
|
+
# will only zip up to the number of the receiver's elements if the receiver
|
38
|
+
# is shorter than the argument Arrays. This method will zip nils instead of
|
39
|
+
# stopping.
|
40
|
+
#
|
41
|
+
# [1, 2].zip([3, 4], [5, 6, 7]) #=> [[1, 3, 5], [2, 4, 6]]
|
42
|
+
# [1, 2].zip_stretched([3, 4], [5, 6, 7]) #=> [[1, 3, 5], [2, 4, 6], [nil, nil, 7]
|
43
|
+
def zip_stretched(*arys)
|
44
|
+
self.stretch(*arys).zip(*arys)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
Array.send(:extend, MoreCoreExtensions::ArrayStretch::ClassMethods)
|
49
|
+
Array.send(:include, MoreCoreExtensions::ArrayStretch)
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module MoreCoreExtensions::ArrayTableize
|
2
|
+
# Create a string representation of _self_ in a tabular format if self is an
|
3
|
+
# Array of Arrays or an Array of Hashes.
|
4
|
+
#
|
5
|
+
# If an Array of Hashes is passed, the headers are assumed from the keys in
|
6
|
+
# the first element of the Array, and the header option is ignored. Also,
|
7
|
+
# the headers are sorted, unless overridden with options.
|
8
|
+
#
|
9
|
+
# General options:
|
10
|
+
# ::max_width: Maximum column width, in order to limit wide columns.
|
11
|
+
#
|
12
|
+
# Options with Array of Arrays:
|
13
|
+
# ::header: Whether or not the first row of data is a header row. Default is
|
14
|
+
# true.
|
15
|
+
#
|
16
|
+
# Options with Array of Hashes:
|
17
|
+
# ::columns: An Array of keys that define the order of all columns.
|
18
|
+
# ::leading_columns: An Array of keys that should be moved to the left side
|
19
|
+
# of the table. This option is ignored if columns option
|
20
|
+
# is passed.
|
21
|
+
# ::trailing_columns: An Array of keys that should be moved to the right side
|
22
|
+
# of the table. This option is ignored if columns option
|
23
|
+
# is passed.
|
24
|
+
#
|
25
|
+
# [["Col1", "Col2"], ["Val1", "Val2"], ["Value3", "Value4"]].tableize #=>
|
26
|
+
#
|
27
|
+
# Col1 | Col2
|
28
|
+
# --------+--------
|
29
|
+
# Val1 | Val2
|
30
|
+
# Value3 | Value4
|
31
|
+
#
|
32
|
+
def tableize(options = {})
|
33
|
+
case self.first
|
34
|
+
when Array; tableize_arrays(options)
|
35
|
+
when Hash; tableize_hashes(options)
|
36
|
+
else raise "must be an Array of Arrays or Array of Hashes"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def tableize_arrays(options)
|
43
|
+
options[:header] = true unless options.has_key?(:header)
|
44
|
+
|
45
|
+
widths = []
|
46
|
+
justifications = []
|
47
|
+
self.each do |row|
|
48
|
+
row.each_with_index do |field, field_i|
|
49
|
+
widths[field_i] = [widths[field_i].to_i, field.to_s.length].max
|
50
|
+
widths[field_i] = [options[:max_width], widths[field_i].to_i].min if options[:max_width]
|
51
|
+
|
52
|
+
justifications[field_i] = field.kind_of?(Numeric) ? "" : "-"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
header_separator = widths.collect { |w| "-" * (w + 2) }.join("+")
|
57
|
+
|
58
|
+
table = []
|
59
|
+
self.each_with_index do |row, row_i|
|
60
|
+
r = []
|
61
|
+
row.each_with_index do |field, field_i|
|
62
|
+
r << sprintf("%0#{justifications[field_i]}#{widths[field_i]}s", field.to_s.gsub(/\n|\r/, '').slice(0, widths[field_i]))
|
63
|
+
end
|
64
|
+
r = " #{r.join(' | ')} ".rstrip
|
65
|
+
|
66
|
+
table << r
|
67
|
+
table << header_separator if row_i == 0 && options[:header]
|
68
|
+
end
|
69
|
+
table.join("\n") << "\n"
|
70
|
+
end
|
71
|
+
|
72
|
+
def tableize_hashes(options)
|
73
|
+
if options[:columns]
|
74
|
+
keys = options[:columns]
|
75
|
+
elsif options[:leading_columns] || options[:trailing_columns]
|
76
|
+
keys = self.first.keys.sort_by(&:to_s)
|
77
|
+
options[:leading_columns].reverse.each { |h| keys.unshift(keys.delete(h)) } if options[:leading_columns]
|
78
|
+
options[:trailing_columns].each { |h| keys.push(keys.delete(h)) } if options[:trailing_columns]
|
79
|
+
else
|
80
|
+
keys = self.first.keys.sort_by(&:to_s)
|
81
|
+
end
|
82
|
+
|
83
|
+
options = options.dup
|
84
|
+
options[:header] = true
|
85
|
+
self.collect { |h| h.values_at(*keys) }.unshift(keys).tableize(options)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
Array.send(:include, MoreCoreExtensions::ArrayTableize)
|
@@ -0,0 +1,5 @@
|
|
1
|
+
require 'more_core_extensions/core_ext/array/duplicates'
|
2
|
+
require 'more_core_extensions/core_ext/array/inclusions'
|
3
|
+
require 'more_core_extensions/core_ext/array/random'
|
4
|
+
require 'more_core_extensions/core_ext/array/stretch'
|
5
|
+
require 'more_core_extensions/core_ext/array/tableize'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'active_support/core_ext/object/blank'
|
2
|
+
|
3
|
+
module MoreCoreExtensions::HashDeletes
|
4
|
+
# Deletes all keys where the value is nil
|
5
|
+
#
|
6
|
+
# {:a => 1, :b => [], :c => nil}.delete_nils # => {:a => 1, :b => []}
|
7
|
+
def delete_nils
|
8
|
+
delete_if { |k, v| v.nil? }
|
9
|
+
end
|
10
|
+
|
11
|
+
# Deletes all keys where the value is blank
|
12
|
+
#
|
13
|
+
# {:a => 1, :b => [], :c => nil}.delete_blanks # => {:a => 1}
|
14
|
+
def delete_blanks
|
15
|
+
delete_if { |k, v| v.blank? }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Hash.send(:include, MoreCoreExtensions::HashDeletes)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module MoreCoreExtensions::HashNested
|
2
|
+
def fetch_path(*args)
|
3
|
+
args = args.first if args.length == 1 && args.first.kind_of?(Array)
|
4
|
+
raise ArgumentError, "must pass at least one key" if args.empty?
|
5
|
+
|
6
|
+
child = self[args.first]
|
7
|
+
return child if args.length == 1
|
8
|
+
return nil unless child.kind_of?(Hash)
|
9
|
+
return child.fetch_path(args[1..-1])
|
10
|
+
end
|
11
|
+
|
12
|
+
def has_key_path?(*args)
|
13
|
+
args = args.first if args.length == 1 && args.first.kind_of?(Array)
|
14
|
+
raise ArgumentError, "must pass at least one key" if args.empty?
|
15
|
+
|
16
|
+
key = args.first
|
17
|
+
has_child = self.has_key?(key)
|
18
|
+
return has_child if args.length == 1
|
19
|
+
|
20
|
+
child = self[key]
|
21
|
+
return false unless child.kind_of?(Hash)
|
22
|
+
return child.has_key_path?(args[1..-1])
|
23
|
+
end
|
24
|
+
alias include_path? has_key_path?
|
25
|
+
alias key_path? has_key_path?
|
26
|
+
alias member_path? has_key_path?
|
27
|
+
|
28
|
+
def store_path(*args)
|
29
|
+
raise ArgumentError, "must pass at least one key, and a value" if args.length < 2
|
30
|
+
value = args.pop
|
31
|
+
args = args.first if args.length == 1 && args.first.kind_of?(Array)
|
32
|
+
|
33
|
+
key = args.first
|
34
|
+
if args.length == 1
|
35
|
+
self[key] = value
|
36
|
+
else
|
37
|
+
child = self[key]
|
38
|
+
child = self[key] = {} unless child.kind_of?(Hash)
|
39
|
+
child.store_path(args[1..-1], value)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def delete_path(*args)
|
44
|
+
args = args.first if args.length == 1 && args.first.kind_of?(Array)
|
45
|
+
raise ArgumentError, "must pass at least one key" if args.empty?
|
46
|
+
|
47
|
+
key = args.first
|
48
|
+
if args.length == 1 || !(child = self[key]).kind_of?(Hash)
|
49
|
+
self.delete(key)
|
50
|
+
else
|
51
|
+
child.delete_path(args[1..-1])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
Hash.send(:include, MoreCoreExtensions::HashNested)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module MoreCoreExtensions::StringFormats
|
2
|
+
# From: Regular Expression Cookbook: 4.1 Validate Email Addresses
|
3
|
+
RE_EMAIL = %r{\A[\w!#$\%&'*+/=?`\{|\}~^-]+(?:\.[\w!#$\%&'*+/=?`\{|\}~^-]+)*@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\Z}i
|
4
|
+
def email?
|
5
|
+
!!(self =~ RE_EMAIL)
|
6
|
+
end
|
7
|
+
|
8
|
+
# From: Regular Expression Cookbook: 7.15 Validating Domain Names
|
9
|
+
RE_DOMAINNAME = %r{^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$}i
|
10
|
+
def domain_name?
|
11
|
+
!!(self =~ RE_DOMAINNAME)
|
12
|
+
end
|
13
|
+
|
14
|
+
# From: Regular Expression Cookbook: 7.16 Matching IPv4 Addresses
|
15
|
+
RE_IPV4 = %r{^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$}
|
16
|
+
def ipv4?
|
17
|
+
!!(self =~ RE_IPV4)
|
18
|
+
end
|
19
|
+
|
20
|
+
# From: Regular Expression Cookbook: 7.17 Matching IPv6 Addresses
|
21
|
+
RE_IPV6 = %r{^(?:(?:(?:[A-F0-9]{1,4}:){6}|(?=(?:[A-F0-9]{0,4}:){0,6}(?:[0-9]{1,3}\.){3}[0-9]{1,3}$)(([0-9A-F]{1,4}:){0,5}|:)((:[0-9A-F]{1,4}){1,5}:|:))(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}|(?=(?:[A-F0-9]{0,4}:){0,7}[A-F0-9]{0,4}$)(([0-9A-F]{1,4}:){1,7}|:)((:[0-9A-F]{1,4}){1,7}|:))$}i
|
22
|
+
def ipv6?
|
23
|
+
!!(self =~ RE_IPV6)
|
24
|
+
end
|
25
|
+
|
26
|
+
def ipaddress?
|
27
|
+
ipv4? || ipv6?
|
28
|
+
end
|
29
|
+
|
30
|
+
RE_INTEGER = %r{^[0-9]+$}
|
31
|
+
def integer?
|
32
|
+
!!(self =~ RE_INTEGER)
|
33
|
+
end
|
34
|
+
|
35
|
+
RE_GUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
|
36
|
+
def guid?
|
37
|
+
!!(self =~ RE_GUID)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
String.send(:include, MoreCoreExtensions::StringFormats)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module MoreCoreExtensions::StringHexDump
|
2
|
+
# Dumps the string in a hex editor style format. Options include:
|
3
|
+
#
|
4
|
+
# :grouping:: The number of bytes in a line. Default is 16.
|
5
|
+
# :newline:: Whether or not to add a \n after each line. Default is true.
|
6
|
+
# :start_pos:: The number at which byte counts will start. Default is 0.
|
7
|
+
# :obj:: Used in conjunction with _:meth_ to send each line to an object
|
8
|
+
# instead of returning as a string.
|
9
|
+
# :meth:: Used in conjunction with _:obj_ to send each line to an object
|
10
|
+
# instead of returning as a string.
|
11
|
+
def hex_dump(*opts)
|
12
|
+
opts = opts[0] if opts.empty? || (opts.length == 1 && opts[0].kind_of?(Hash))
|
13
|
+
raise ArgumentError, "opts must be a Hash" unless opts.nil? || opts.kind_of?(Hash)
|
14
|
+
|
15
|
+
opts = {:grouping => 16, :newline => true, :start_pos => 0}.merge!(opts || {})
|
16
|
+
obj, meth, grouping, newline, pos = opts.values_at(:obj, :meth, :grouping, :newline, :start_pos)
|
17
|
+
raise ArgumentError, "obj and meth must both be set, or both not set" if (obj.nil? && !meth.nil?) || (!obj.nil? && meth.nil?)
|
18
|
+
|
19
|
+
row_format = "0x%08x #{"%02x " * grouping} "
|
20
|
+
|
21
|
+
i = 0
|
22
|
+
last_i = self.length - 1
|
23
|
+
|
24
|
+
ret = ''
|
25
|
+
row_vals = []
|
26
|
+
row_chars = ''
|
27
|
+
|
28
|
+
self.each_byte do |c|
|
29
|
+
row_vals << c
|
30
|
+
row_chars << (c < 0x20 || (c >= 0x7F && c < 0xA0) ? '.' : c.chr)
|
31
|
+
|
32
|
+
if (i + 1) % grouping == 0 || i == last_i
|
33
|
+
row_format = "0x%08x #{"%02x " * row_vals.length}#{" " * (grouping - row_vals.length)} " if i == last_i
|
34
|
+
|
35
|
+
row_vals.unshift(pos)
|
36
|
+
ret << (row_format % row_vals) << row_chars
|
37
|
+
ret << "\n" if newline
|
38
|
+
if obj
|
39
|
+
obj.send(meth, ret)
|
40
|
+
ret.replace('')
|
41
|
+
end
|
42
|
+
|
43
|
+
pos += grouping
|
44
|
+
row_vals.clear
|
45
|
+
row_chars = ''
|
46
|
+
end
|
47
|
+
|
48
|
+
i += 1
|
49
|
+
end
|
50
|
+
|
51
|
+
return ret
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
String.send(:include, MoreCoreExtensions::StringHexDump)
|
@@ -0,0 +1 @@
|
|
1
|
+
require "more_core_extensions/version"
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'more_core_extensions/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "more_core_extensions"
|
8
|
+
spec.version = MoreCoreExtensions::VERSION
|
9
|
+
spec.authors = ["Jason Frey"]
|
10
|
+
spec.email = ["fryguy9@gmail.com"]
|
11
|
+
spec.description = %q{MoreCoreExtensions are a set of core extensions beyond those provided by ActiveSupport.}
|
12
|
+
spec.summary = spec.description
|
13
|
+
spec.homepage = "http://github.com/ManageIQ/more_core_extensions"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
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", "~> 1.3"
|
22
|
+
spec.add_development_dependency "coveralls"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "rspec"
|
25
|
+
|
26
|
+
spec.add_dependency "activesupport"
|
27
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require_relative "../../spec_helper"
|
2
|
+
|
3
|
+
describe Array do
|
4
|
+
it '#duplicates' do
|
5
|
+
[1, 2, 3, 4].duplicates.should be_empty
|
6
|
+
[1, 2, 3, 4, 2, 4].duplicates.should match_array [2, 4]
|
7
|
+
|
8
|
+
['1', '2', '3', '4'].duplicates.should be_empty
|
9
|
+
['1', '2', '3', '4', '2', '4'].duplicates.should match_array ['2', '4']
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative "../../spec_helper"
|
2
|
+
|
3
|
+
describe Array do
|
4
|
+
it '#include_any?' do
|
5
|
+
[1, 2, 3].include_any?(1, 2).should be_true
|
6
|
+
[1, 2, 3].include_any?(1, 4).should be_true
|
7
|
+
[1, 2, 3].include_any?(4, 5).should be_false
|
8
|
+
|
9
|
+
['1', '2', '3'].include_any?('1', '2').should be_true
|
10
|
+
['1', '2', '3'].include_any?('1', '4').should be_true
|
11
|
+
['1', '2', '3'].include_any?('4', '5').should be_false
|
12
|
+
end
|
13
|
+
|
14
|
+
it '#include_none?' do
|
15
|
+
[1, 2, 3].include_none?(1, 2).should be_false
|
16
|
+
[1, 2, 3].include_none?(1, 4).should be_false
|
17
|
+
[1, 2, 3].include_none?(4, 5).should be_true
|
18
|
+
|
19
|
+
['1', '2', '3'].include_none?('1', '2').should be_false
|
20
|
+
['1', '2', '3'].include_none?('1', '4').should be_false
|
21
|
+
['1', '2', '3'].include_none?('4', '5').should be_true
|
22
|
+
end
|
23
|
+
|
24
|
+
it '#include_all?' do
|
25
|
+
[1, 2, 3].include_all?(1, 2).should be_true
|
26
|
+
[1, 2, 3].include_all?(1, 4).should be_false
|
27
|
+
[1, 2, 3].include_all?(4, 5).should be_false
|
28
|
+
|
29
|
+
['1', '2', '3'].include_all?('1', '2').should be_true
|
30
|
+
['1', '2', '3'].include_all?('1', '4').should be_false
|
31
|
+
['1', '2', '3'].include_all?('4', '5').should be_false
|
32
|
+
end
|
33
|
+
end
|