dm_ruby_extensions 1.0.8 → 1.5.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 +5 -5
- data/.github/workflow/ci.yml +41 -0
- data/.gitignore +0 -3
- data/.rubocop.yml +26 -0
- data/.ruby-version +1 -0
- data/Gemfile +5 -1
- data/README.md +3 -1
- data/Rakefile +6 -4
- data/bin/console +18 -0
- data/dm_ruby_extensions.gemspec +15 -12
- data/lib/dm_ruby_extensions/extend_array.rb +9 -8
- data/lib/dm_ruby_extensions/extend_date.rb +7 -8
- data/lib/dm_ruby_extensions/extend_datetime.rb +6 -7
- data/lib/dm_ruby_extensions/extend_false.rb +2 -3
- data/lib/dm_ruby_extensions/extend_hash.rb +36 -28
- data/lib/dm_ruby_extensions/extend_integer.rb +6 -5
- data/lib/dm_ruby_extensions/extend_nil.rb +11 -11
- data/lib/dm_ruby_extensions/extend_numeric.rb +5 -5
- data/lib/dm_ruby_extensions/extend_string.rb +68 -65
- data/lib/dm_ruby_extensions/extend_time.rb +4 -5
- data/lib/dm_ruby_extensions/extend_true.rb +2 -3
- data/lib/dm_ruby_extensions/version.rb +3 -1
- data/lib/dm_ruby_extensions.rb +15 -12
- data/spec/extensions/array_spec.rb +13 -12
- data/spec/extensions/date_spec.rb +8 -7
- data/spec/extensions/datetime_spec.rb +8 -7
- data/spec/extensions/false_spec.rb +3 -4
- data/spec/extensions/hash_spec.rb +20 -17
- data/spec/extensions/integer_spec.rb +3 -3
- data/spec/extensions/nil_spec.rb +7 -7
- data/spec/extensions/numeric_spec.rb +3 -3
- data/spec/extensions/string_spec.rb +50 -39
- data/spec/extensions/time_spec.rb +4 -3
- data/spec/extensions/true_spec.rb +3 -4
- data/spec/spec_helper.rb +45 -44
- metadata +14 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a52656d8cd06524cb3619c98f8ee54221bbe7099bd8583ac3f6635a3fca73ad1
|
4
|
+
data.tar.gz: 8563dfd8ae1a2d76e5d07fbc6d4b09ce84f01f0970de0344ed6da46bb69f3819
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 58dc5a359f374ca974e993472c29ea2649a0855856f03335bd276f5aed0bedb490dee6ea34309e714cbdbce9253c54fdb5ca5c02fa3115b0acf64d681b689b83
|
7
|
+
data.tar.gz: 7e9f70201a41ac2f623214e27af7cd1549984174e4f5bea5e578a8f8898a18f931a546799293feba8449918402f77ac51ea4f2e5ca100f3124fb3d5499f862dd
|
@@ -0,0 +1,41 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
pull_request:
|
5
|
+
|
6
|
+
jobs:
|
7
|
+
rspec:
|
8
|
+
strategy:
|
9
|
+
fail-fast: false
|
10
|
+
matrix:
|
11
|
+
os:
|
12
|
+
- ubuntu-latest
|
13
|
+
- macos-latest
|
14
|
+
ruby-version: [3.0, 3.1, 3.2, 'ruby-head']
|
15
|
+
|
16
|
+
runs-on: ${{ matrix.os }}
|
17
|
+
|
18
|
+
steps:
|
19
|
+
- uses: actions/checkout@v4
|
20
|
+
|
21
|
+
- name: Set up Ruby ${{ matrix.ruby-version }}
|
22
|
+
uses: ruby/setup-ruby@v1
|
23
|
+
with:
|
24
|
+
ruby-version: ${{ matrix.ruby-version }}
|
25
|
+
bundler-cache: true # 'bundle install' and cache
|
26
|
+
|
27
|
+
- name: Run ${{ matrix.os }} tests
|
28
|
+
run: bundle install
|
29
|
+
run: bundle exec rspec
|
30
|
+
|
31
|
+
rubocop:
|
32
|
+
runs-on: ubuntu-latest
|
33
|
+
|
34
|
+
steps:
|
35
|
+
- uses: actions/checkout@v4
|
36
|
+
|
37
|
+
- name: Set up Ruby ${{ matrix.ruby-version }}
|
38
|
+
uses: ruby/setup-ruby@v1
|
39
|
+
- name: Run rubocop
|
40
|
+
run: bundle install
|
41
|
+
run: bundle exec rubocop
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- '**/tmp/**/*'
|
4
|
+
CacheRootDirectory: tmp
|
5
|
+
UseCache: false
|
6
|
+
|
7
|
+
Metrics/BlockLength:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
Metrics/MethodLength:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Metrics/AbcSize:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
Metrics/CyclomaticComplexity:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Metrics/ClassLength:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Metrics/PerceivedComplexity:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Style/Documentation:
|
26
|
+
Enabled: false
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.2.2
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -3,7 +3,9 @@
|
|
3
3
|
[](http://badge.fury.io/rb/dm_ruby_extensions)
|
4
4
|
[](https://travis-ci.com/digitalmoksha/dm_ruby_extensions)
|
5
5
|
|
6
|
-
Adds some simple
|
6
|
+
Adds some simple convenience methods to some Ruby classes, for use in the digitalMoksha gems.
|
7
|
+
Although some of these can be found in other libraries, this includes a small handful and
|
8
|
+
removes the dependency on another large library.
|
7
9
|
|
8
10
|
## Installation
|
9
11
|
|
data/Rakefile
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
3
5
|
|
4
6
|
RSpec::Core::RakeTask.new
|
5
7
|
|
6
|
-
task :
|
7
|
-
task :
|
8
|
+
task default: :spec
|
9
|
+
task test: :spec
|
data/bin/console
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'dm_ruby_extensions'
|
6
|
+
require 'irb'
|
7
|
+
|
8
|
+
puts <<~TEXT
|
9
|
+
-------------------
|
10
|
+
Example Usage:
|
11
|
+
|
12
|
+
'1'.as_boolean
|
13
|
+
(Date.today - 12.years).to_age
|
14
|
+
-------------------
|
15
|
+
|
16
|
+
TEXT
|
17
|
+
|
18
|
+
IRB.start(__FILE__)
|
data/dm_ruby_extensions.gemspec
CHANGED
@@ -1,21 +1,24 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'dm_ruby_extensions/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |gem|
|
7
|
-
gem.name =
|
8
|
+
gem.name = 'dm_ruby_extensions'
|
8
9
|
gem.version = DmRubyExtensions::VERSION
|
9
|
-
gem.authors = [
|
10
|
-
gem.email = [
|
11
|
-
gem.description =
|
12
|
-
gem.summary =
|
13
|
-
gem.homepage =
|
10
|
+
gem.authors = ['Brett Walker']
|
11
|
+
gem.email = ['github@digitalmoksha.com']
|
12
|
+
gem.description = 'Ruby base class extensions'
|
13
|
+
gem.summary = 'Simple Ruby base class extensions'
|
14
|
+
gem.homepage = 'https://github.com/digitalmoksha/dm_ruby_extensions'
|
14
15
|
gem.licenses = ['MIT']
|
15
16
|
|
16
|
-
gem.files = `git ls-files`.split(
|
17
|
+
gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
17
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
-
gem.require_paths = [
|
19
|
-
|
20
|
-
gem.
|
19
|
+
gem.require_paths = ['lib']
|
20
|
+
|
21
|
+
gem.required_ruby_version = '~> 3.0'
|
22
|
+
|
23
|
+
gem.add_dependency 'activesupport', '>= 6.0'
|
21
24
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#------------------------------------------------------------------------------
|
2
4
|
class Array
|
3
|
-
|
4
|
-
#
|
5
|
+
# Extract options from a set of arguments. Removes and returns the last element
|
6
|
+
# in the array if it's a hash, otherwise returns a blank hash.
|
5
7
|
#
|
6
8
|
# def options(*args)
|
7
9
|
# args.extract_options!
|
@@ -19,7 +21,7 @@ class Array
|
|
19
21
|
# [0,5,7,8,11,16].closest_max(7) => 7
|
20
22
|
#------------------------------------------------------------------------------
|
21
23
|
def closest_max(value)
|
22
|
-
self.select{|item| item <= value}.max
|
24
|
+
self.select { |item| item <= value }.max
|
23
25
|
end
|
24
26
|
|
25
27
|
# able to join safe and unsafe strings
|
@@ -27,7 +29,7 @@ class Array
|
|
27
29
|
def xss_aware_join(delimiter = '')
|
28
30
|
''.html_safe.tap do |str|
|
29
31
|
each_with_index do |element, i|
|
30
|
-
str << delimiter if i
|
32
|
+
str << delimiter if i.positive?
|
31
33
|
str << element
|
32
34
|
end
|
33
35
|
end
|
@@ -35,12 +37,11 @@ class Array
|
|
35
37
|
|
36
38
|
# given an array of css classes/styles, join them into one string.
|
37
39
|
# only join non-nil/non-empty strings, and return nil if the result
|
38
|
-
# is an empty string (rails tag methods will not include the
|
40
|
+
# is an empty string (rails tag methods will not include the
|
39
41
|
# attribute if it is nil, which is desirable for cleaner html)
|
40
42
|
#------------------------------------------------------------------------------
|
41
|
-
def css_join(
|
42
|
-
str =
|
43
|
+
def css_join(_delimiter = '')
|
44
|
+
str = flatten.delete_if { |x| x.nil? || x == '' }.join(' ')
|
43
45
|
str == '' ? nil : str
|
44
46
|
end
|
45
47
|
end
|
46
|
-
|
@@ -1,23 +1,22 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
class Date
|
3
4
|
# http://stackoverflow.com/questions/819263/get-persons-age-in-ruby
|
4
5
|
#------------------------------------------------------------------------------
|
5
6
|
def to_age
|
6
7
|
now = Time.now.utc.to_date
|
7
|
-
now.year -
|
8
|
+
now.year - year - (now.month > month || (now.month == month && now.day >= day) ? 0 : 1)
|
8
9
|
end
|
9
|
-
|
10
|
+
|
10
11
|
#------------------------------------------------------------------------------
|
11
12
|
def localize(options = {})
|
12
|
-
options = {:
|
13
|
-
I18n.localize(self, options)
|
13
|
+
options = { format: options } if options.instance_of?(String)
|
14
|
+
I18n.localize(self, **options)
|
14
15
|
end
|
15
16
|
|
16
17
|
# Create a unique sortable index for this date
|
17
18
|
#------------------------------------------------------------------------------
|
18
19
|
def to_index
|
19
|
-
yday + (year-2000) * 1000
|
20
|
+
yday + (year - 2000) * 1000
|
20
21
|
end
|
21
|
-
|
22
22
|
end
|
23
|
-
|
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#------------------------------------------------------------------------------
|
2
4
|
class DateTime
|
3
|
-
|
4
5
|
#------------------------------------------------------------------------------
|
5
6
|
def to_age
|
6
7
|
(DateTime.now - self).to_i / 365
|
@@ -8,15 +9,13 @@ class DateTime
|
|
8
9
|
|
9
10
|
#------------------------------------------------------------------------------
|
10
11
|
def localize(options = {})
|
11
|
-
options = {:
|
12
|
-
I18n.localize(self, options)
|
12
|
+
options = { format: options } if options.instance_of?(String)
|
13
|
+
I18n.localize(self, **options)
|
13
14
|
end
|
14
|
-
|
15
|
+
|
15
16
|
# Create a unique sortable index for this date
|
16
17
|
#------------------------------------------------------------------------------
|
17
18
|
def to_index
|
18
|
-
yday + (year-2000) * 1000
|
19
|
+
yday + (year - 2000) * 1000
|
19
20
|
end
|
20
|
-
|
21
21
|
end
|
22
|
-
|
@@ -1,30 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#------------------------------------------------------------------------------
|
2
4
|
class Hash
|
3
|
-
|
4
|
-
# takes a Hash (like the params hash), and converts the Rails date attributes
|
5
|
+
# takes a Hash (like the params hash), and converts the Rails date attributes
|
5
6
|
# to a real Date object.
|
6
|
-
# {'start_date(1i)' => 2012, 'start_date(2i)' => 11, 'start_date(3i)' => 23}.convert_date(:start_date)
|
7
|
+
# {'start_date(1i)' => 2012, 'start_date(2i)' => 11, 'start_date(3i)' => 23}.convert_date(:start_date)
|
7
8
|
#------------------------------------------------------------------------------
|
8
9
|
def convert_date(date_symbol_or_string)
|
9
10
|
attribute = date_symbol_or_string.to_s
|
10
|
-
return nil if self[attribute
|
11
|
-
|
11
|
+
return nil if self["#{attribute}(1i)"].nil? || self["#{attribute}(2i)"].nil? || self["#{attribute}(3i)"].nil?
|
12
|
+
|
13
|
+
Date.new(self["#{attribute}(1i)"].to_i, self["#{attribute}(2i)"].to_i, self["#{attribute}(3i)"].to_i)
|
12
14
|
end
|
13
15
|
|
14
|
-
# takes a Hash (like the params hash), and converts the Rails datetime attributes
|
16
|
+
# takes a Hash (like the params hash), and converts the Rails datetime attributes
|
15
17
|
# to a real Date object.
|
16
18
|
#------------------------------------------------------------------------------
|
17
19
|
def convert_datetime(date_symbol_or_string)
|
18
20
|
attribute = date_symbol_or_string.to_s
|
19
|
-
|
20
|
-
|
21
|
+
if self["#{attribute}(1i)"].nil? || self["#{attribute}(2i)"].nil? ||
|
22
|
+
self["#{attribute}(3i)"].nil? || self["#{attribute}(4i)"].nil? ||
|
23
|
+
self["#{attribute}(5i)"].nil?
|
24
|
+
return nil
|
25
|
+
end
|
26
|
+
|
27
|
+
Time.local(self["#{attribute}(1i)"].to_i, self["#{attribute}(2i)"].to_i, self["#{attribute}(3i)"].to_i,
|
28
|
+
self["#{attribute}(4i)"].to_i, self["#{attribute}(5i)"].to_i)
|
21
29
|
end
|
22
30
|
|
23
31
|
# Convert hash of parameters to a query string
|
24
32
|
#------------------------------------------------------------------------------
|
33
|
+
# rubocop:disable Style/OptionalBooleanParameter
|
25
34
|
def url_query_string(leading_slash = true)
|
26
|
-
|
35
|
+
"#{leading_slash ? '/?' : '?'}#{to_query}"
|
27
36
|
end
|
37
|
+
# rubocop:enable Style/OptionalBooleanParameter
|
28
38
|
|
29
39
|
# Borrowed from https://github.com/rubyworks/facets
|
30
40
|
#------------------------------------------------------------------------------
|
@@ -42,7 +52,7 @@ class Hash
|
|
42
52
|
# foo.rekey(:b=>:x) #=> { :a =>1, :x=>2 }
|
43
53
|
# foo.rekey('foo'=>'bar') #=> { :a =>1, :b=>2 }
|
44
54
|
#
|
45
|
-
# If a block is given, converts all keys in the Hash
|
55
|
+
# If a block is given, converts all keys in the Hash according to the
|
46
56
|
# given block procedure.
|
47
57
|
#
|
48
58
|
# foo = { :name=>'Gavin', :wife=>:Lisa }
|
@@ -55,37 +65,36 @@ class Hash
|
|
55
65
|
# Raises an ArgumentError if both a +key_map+ and a block are given.
|
56
66
|
# If both are needed just call #rekey twice.
|
57
67
|
#
|
58
|
-
# TODO: If `nil` is returned by block should the key be set to `nil` or the
|
68
|
+
# TODO: If `nil` is returned by block should the key be set to `nil` or the original key?
|
59
69
|
#
|
60
70
|
# CREDIT: Trans, Gavin Kistner
|
71
|
+
def rekey(key_map = nil, &block)
|
72
|
+
raise ArgumentError, 'argument or block' if key_map && block
|
61
73
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
if !(key_map or block)
|
66
|
-
block = lambda{|k| k.to_sym}
|
74
|
+
unless key_map || block
|
75
|
+
block = lambda { |k| k.to_sym } # rubocop:disable Style/SymbolProc, Style/Lambda
|
67
76
|
end
|
68
77
|
|
69
78
|
if block
|
70
79
|
hash = dup.clear
|
71
80
|
if block.arity.abs == 1
|
72
81
|
each_pair do |k, v|
|
73
|
-
hash[block[k]] = v
|
82
|
+
hash[block[k]] = v # hash[block[k] || k] = v
|
74
83
|
end
|
75
84
|
else
|
76
85
|
each_pair do |k, v|
|
77
|
-
hash[block[k,v]] = v
|
86
|
+
hash[block[k, v]] = v # hash[block[k,v] || k] = v
|
78
87
|
end
|
79
88
|
end
|
80
89
|
else
|
81
|
-
#hash = dup.clear # to keep default_proc
|
82
|
-
#(keys - key_map.keys).each do |key|
|
83
|
-
#
|
84
|
-
#end
|
85
|
-
#key_map.each do |from, to|
|
86
|
-
#
|
87
|
-
#end
|
88
|
-
hash = dup
|
90
|
+
# hash = dup.clear # to keep default_proc
|
91
|
+
# (keys - key_map.keys).each do |key|
|
92
|
+
# hash[key] = self[key]
|
93
|
+
# end
|
94
|
+
# key_map.each do |from, to|
|
95
|
+
# hash[to] = self[from] if key?(from)
|
96
|
+
# end
|
97
|
+
hash = dup # to keep default_proc
|
89
98
|
key_map.each_pair do |from, to|
|
90
99
|
hash[to] = hash.delete(from) if hash.key?(from)
|
91
100
|
end
|
@@ -102,8 +111,7 @@ class Hash
|
|
102
111
|
#
|
103
112
|
# CREDIT: Trans, Gavin Kistner
|
104
113
|
|
105
|
-
def rekey!(key_map=nil, &block)
|
114
|
+
def rekey!(key_map = nil, &block)
|
106
115
|
replace(rekey(key_map, &block))
|
107
116
|
end
|
108
|
-
|
109
117
|
end
|
@@ -1,16 +1,17 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
class Integer
|
3
4
|
# Factorial of number
|
4
5
|
# 5.factorial == 5 x 4 x 3 x 2 x 1 == 120
|
5
6
|
#------------------------------------------------------------------------------
|
6
7
|
def factorial
|
7
|
-
return 1 if
|
8
|
+
return 1 if zero?
|
9
|
+
|
8
10
|
(1..self).inject(:*)
|
9
11
|
end
|
10
12
|
|
11
13
|
#------------------------------------------------------------------------------
|
12
14
|
def as_boolean
|
13
|
-
|
15
|
+
positive? ? true : false
|
14
16
|
end
|
15
|
-
|
16
|
-
end
|
17
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# If nil, then return a default string
|
2
4
|
#------------------------------------------------------------------------------
|
3
|
-
class NilClass
|
4
|
-
|
5
|
+
class NilClass # :nodoc:
|
5
6
|
#------------------------------------------------------------------------------
|
6
7
|
def to_s_default(default_str = 'n/a')
|
7
8
|
default_str
|
@@ -11,7 +12,7 @@ class NilClass #:nodoc:
|
|
11
12
|
def as_boolean
|
12
13
|
false
|
13
14
|
end
|
14
|
-
|
15
|
+
|
15
16
|
#------------------------------------------------------------------------------
|
16
17
|
def to_age
|
17
18
|
0
|
@@ -19,18 +20,17 @@ class NilClass #:nodoc:
|
|
19
20
|
|
20
21
|
#------------------------------------------------------------------------------
|
21
22
|
def sql_wildcard
|
22
|
-
|
23
|
+
'%'
|
23
24
|
end
|
24
|
-
|
25
|
+
|
25
26
|
#------------------------------------------------------------------------------
|
26
27
|
def utc
|
27
|
-
|
28
|
+
''
|
28
29
|
end
|
29
|
-
|
30
|
+
|
30
31
|
# if nil + something, just return something
|
31
32
|
#------------------------------------------------------------------------------
|
32
|
-
def +(
|
33
|
-
|
33
|
+
def +(other)
|
34
|
+
other
|
34
35
|
end
|
35
|
-
|
36
|
-
end
|
36
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Numeric
|
2
|
-
|
3
4
|
#------------------------------------------------------------------------------
|
4
|
-
def percent_of(
|
5
|
-
|
5
|
+
def percent_of(num, precision = 0)
|
6
|
+
num.zero? ? 0 : (to_f / num * 100.0).round(precision)
|
6
7
|
end
|
7
|
-
|
8
|
-
end
|
8
|
+
end
|