more_core_extensions 4.0.0 → 4.3.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef4118bf7eac11398770bff4fe85a32527febec7e9d8d45a4c3c91f527e4bac5
4
- data.tar.gz: c48abbcc780d5cbe1d6284de32c106795cb0d1a268b8adb3f6212c6e838c1228
3
+ metadata.gz: fb3f91f72b2c1bc1462184ddab53609ba5b5b09f733eb78f0c34c89e7851f507
4
+ data.tar.gz: b78bda65aa6f835881b77e069cb1d010fb32dddf72d46c2b67187085a36f88f3
5
5
  SHA512:
6
- metadata.gz: 62c7e0dc1b63655c03c509899d60e9224e310626ceff3be2095ce4008165692877b9099a86f2a0768eae414831b24ac733d160dbb2cb2fb7ded18cdbc56488b2
7
- data.tar.gz: f4921953a78e5370e90946da2ec7f6456124f3078688f6d0cc901857d9b5b6b98c5e8c4f34f43b885d8bb79ee62c80a45cacf9baf56a95f384b78070e1699a3f
6
+ metadata.gz: 955082c21b2f443dcdd3d888d85e22086a80cb9cbe6cce425c2a8293d20550d52052cd67512cd31faa8333d5318d06ee240a5c33a3c8090f2d4cb56f1df636d1
7
+ data.tar.gz: 7e149a0ee4d1f68258a5a8d76d26d6f4a0b92ab8e39f496c6becc43cbb455e03e0091cf4530cc3ca5cd575d07ddd58761b5ad33944d0887316358e382498ae08
data/.codeclimate.yml ADDED
@@ -0,0 +1,16 @@
1
+ prepare:
2
+ fetch:
3
+ - url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/.rubocop_base.yml
4
+ path: ".rubocop_base.yml"
5
+ - url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/.rubocop_cc_base.yml
6
+ path: ".rubocop_cc_base.yml"
7
+ - url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/styles/base.yml
8
+ path: styles/base.yml
9
+ - url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/styles/cc_base.yml
10
+ path: styles/cc_base.yml
11
+ plugins:
12
+ rubocop:
13
+ enabled: true
14
+ config: ".rubocop_cc.yml"
15
+ channel: rubocop-0-82
16
+ version: '2'
data/.rubocop.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  inherit_from:
2
- - https://raw.githubusercontent.com/ManageIQ/guides/master/.rubocop_base.yml
3
- # put all local rubocop config into .rubocop_local.yml as it will be loaded by .rubocop_cc.yml as well
4
- - .rubocop_local.yml
2
+ - ".rubocop_local.yml"
3
+ inherit_gem:
4
+ manageiq-style: ".rubocop_base.yml"
data/.rubocop_cc.yml ADDED
@@ -0,0 +1,4 @@
1
+ inherit_from:
2
+ - ".rubocop_base.yml"
3
+ - ".rubocop_cc_base.yml"
4
+ - ".rubocop_local.yml"
data/.travis.yml CHANGED
@@ -1,20 +1,14 @@
1
1
  language: ruby
2
2
  rvm:
3
- - "2.0"
4
- - "2.1.10"
5
- - "2.2.10"
6
- - "2.3.8"
7
- - "2.4.5"
8
- - "2.5.3"
9
- - "2.6.0"
3
+ - "2.5.8"
4
+ - "2.6.6"
5
+ - "2.7.2"
10
6
  - ruby-head
11
7
  - jruby-head
12
- sudo: false
13
8
  cache: bundler
14
9
  after_script: bundle exec codeclimate-test-reporter
15
10
  matrix:
16
11
  allow_failures:
17
- - rvm: "2.6.0"
18
12
  - rvm: ruby-head
19
13
  - rvm: jruby-head
20
14
  fast_finish: true
data/CHANGELOG.md CHANGED
@@ -4,6 +4,31 @@ This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [4.3.1] - 2021-07-13
8
+ ### Changed
9
+ - Fix String#to_i_with_method to raise the correct error on private methods [[#101](https://github.com/ManageIQ/more_core_extensions/pull/101)]
10
+ - Fix issue where Array#tableize would not honor a smaller colored field [[#102](https://github.com/ManageIQ/more_core_extensions/pull/102)]
11
+
12
+ ## [4.3.0] - 2020-10-27
13
+ ### Added
14
+ - Add String#to_i_with_method and friends [[#95](https://github.com/ManageIQ/more_core_extensions/pull/95)]
15
+ - Add Object#deep_send [[#94](https://github.com/ManageIQ/more_core_extensions/pull/94)]
16
+
17
+ ## [4.2.0] - 2020-07-20
18
+ ### Added
19
+ - Add bundler-inject allowing developers to override dependencies [[#89](https://github.com/ManageIQ/more_core_extensions/pull/89)]
20
+ - Add Array and Hash #deep_clone and #deep_delete [[#91](https://github.com/ManageIQ/more_core_extensions/pull/91)]
21
+ - Add Digest::UUID.clean to properly format UUID strings [[#81](https://github.com/ManageIQ/more_core_extensions/pull/81)]
22
+
23
+ ### Changed
24
+ - Update ArrayTableize to properly set field width for color text [[#87](https://github.com/ManageIQ/more_core_extensions/pull/87)]
25
+ - Change Array#format_table header output to markdown vs postgres [[#83](https://github.com/ManageIQ/more_core_extensions/pull/83)]
26
+
27
+ ## [4.1.0] - 2020-04-30
28
+ ### Added
29
+ - Added Ruby 2.7 support [[#79](https://github.com/ManageIQ/more_core_extensions/pull/79)]
30
+ - Added Process#pause, Process#resume, and Process#alive? [[#73](https://github.com/ManageIQ/more_core_extensions/pull/73)]
31
+
7
32
  ## [4.0.0] - 2020-01-31
8
33
  ### Changed
9
34
  - **BREAKING**: Moved Object#descendant_get to Class#descendant_get [[#75](https://github.com/ManageIQ/more_core_extensions/pull/75)]
@@ -82,7 +107,13 @@ This project adheres to [Semantic Versioning](http://semver.org/).
82
107
  - Upgraded to RSpec 3 [[#16](https://github.com/ManageIQ/more_core_extensions/pull/16)]
83
108
  - Added the Change Log!
84
109
 
85
- [Unreleased]: https://github.com/ManageIQ/more_core_extensions/compare/v3.7.0...HEAD
110
+ [Unreleased]: https://github.com/ManageIQ/more_core_extensions/compare/v4.3.1...HEAD
111
+ [4.3.1]: https://github.com/ManageIQ/more_core_extensions/compare/v4.3.0...v4.3.1
112
+ [4.3.0]: https://github.com/ManageIQ/more_core_extensions/compare/v4.2.0...v4.3.0
113
+ [4.2.0]: https://github.com/ManageIQ/more_core_extensions/compare/v4.1.0...v4.2.0
114
+ [4.1.0]: https://github.com/ManageIQ/more_core_extensions/compare/v4.0.0...v4.1.0
115
+ [4.0.0]: https://github.com/ManageIQ/more_core_extensions/compare/v3.8.0...v4.0.0
116
+ [3.8.0]: https://github.com/ManageIQ/more_core_extensions/compare/v3.7.0...v3.8.0
86
117
  [3.7.0]: https://github.com/ManageIQ/more_core_extensions/compare/v3.6.0...v3.7.0
87
118
  [3.6.0]: https://github.com/ManageIQ/more_core_extensions/compare/v3.5.0...v3.6.0
88
119
  [3.5.0]: https://github.com/ManageIQ/more_core_extensions/compare/v3.4.0...v3.5.0
data/Gemfile CHANGED
@@ -1,8 +1,16 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ plugin 'bundler-inject'
4
+ require File.join(Bundler::Plugin.index.load_paths("bundler-inject")[0], "bundler-inject") rescue nil
5
+
3
6
  # Specify your gem's dependencies in more_core_extensions.gemspec
4
7
  gemspec
5
8
 
6
- # HACK: Rails 5 dropped support for Ruby < 2.2.2
7
- active_support_version = "< 5" if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.2.2")
9
+ # Rails 5 dropped support for Ruby < 2.2.2
10
+ # Rails 6 dropped support for Ruby < 2.4.4
11
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.2.2")
12
+ active_support_version = "< 5"
13
+ elsif Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.4.4")
14
+ active_support_version = "< 6"
15
+ end
8
16
  gem 'activesupport', active_support_version
data/README.md CHANGED
@@ -19,6 +19,7 @@ MoreCoreExtensions are a set of core extensions beyond those provided by ActiveS
19
19
  * core_ext/array/deletes.rb
20
20
  * `#delete_blanks` - Deletes all items where the value is blank
21
21
  * `#delete_nils` - Deletes all items where the value is nil
22
+ * `#deep_delete` - Deletes nested hash key elements
22
23
  * core_ext/array/duplicates.rb
23
24
  * `#duplicates` - Returns an Array of the duplicates found
24
25
  * core_ext/array/element_counts.rb
@@ -61,6 +62,7 @@ MoreCoreExtensions are a set of core extensions beyond those provided by ActiveS
61
62
  * core_ext/hash/deletes.rb
62
63
  * `#delete_blanks` - Deletes all keys where the value is blank
63
64
  * `#delete_nils` - Deletes all keys where the value is nil
65
+ * `#deep_delete` - Deletes nested hash key elements
64
66
  * core_ext/hash/nested.rb (see [Shared](#shared))
65
67
  * `#delete_blank_paths` - Deletes all paths where the value is blank
66
68
  * core_ext/hash/sorting.rb (see [Shared](#shared))
@@ -87,9 +89,18 @@ MoreCoreExtensions are a set of core extensions beyond those provided by ActiveS
87
89
 
88
90
  #### Object
89
91
 
92
+ * core_ext/module/deep_send.rb
93
+ * `#deep_send` - Invokes the specified methods continuously, unless encountering a nil value.
90
94
  * core_ext/module/namespace.rb
91
95
  * `#in_namespace?` - Returns whether or not the object is in the given namespace
92
96
 
97
+ #### Process
98
+
99
+ * core_ext/process/pause_resume.rb
100
+ * `.pause` - Pauses a process
101
+ * `.resume` - Resumes a paused process
102
+ * `.alive?` - Returns whether or not a process is running
103
+
93
104
  #### Range
94
105
 
95
106
  * core_ext/range/step_value.rb
@@ -113,6 +124,10 @@ MoreCoreExtensions are a set of core extensions beyond those provided by ActiveS
113
124
  * `#hex_dump` - Dumps the string in a hex editor style format
114
125
  * core_ext/string/iec60027_2.rb
115
126
  * `#iec_60027_2_to_i` - Convert strings with an IEC60027-2 suffix to an integer
127
+ * core_ext/string/to_i_with_method.rb
128
+ * `#to_f_with_method` - Converts to a Float while also evaluating a method invocation
129
+ * `#to_i_with_method` - Converts to an Integer while also evaluating a method invocation
130
+ * `#number_with_method?` - Determines if the object contains a number with a method invocation
116
131
 
117
132
  #### Symbol
118
133
 
@@ -122,6 +137,7 @@ MoreCoreExtensions are a set of core extensions beyond those provided by ActiveS
122
137
  #### Shared
123
138
 
124
139
  * core_ext/shared/nested.rb
140
+ * `#deep_clone` - Performs a Marshal based deep clone
125
141
  * `#delete_path` - Delete the value at the specified nesting
126
142
  * `#fetch_path` - Fetch the value at the specified nesting
127
143
  * `#find_path` - Detect which nesting holds the specified value
@@ -3,11 +3,13 @@ require 'more_core_extensions/version'
3
3
  require 'more_core_extensions/core_ext/array'
4
4
  require 'more_core_extensions/core_ext/benchmark'
5
5
  require 'more_core_extensions/core_ext/class'
6
+ require 'more_core_extensions/core_ext/digest'
6
7
  require 'more_core_extensions/core_ext/hash'
7
8
  require 'more_core_extensions/core_ext/math'
8
9
  require 'more_core_extensions/core_ext/module'
9
10
  require 'more_core_extensions/core_ext/numeric'
10
11
  require 'more_core_extensions/core_ext/object'
12
+ require 'more_core_extensions/core_ext/process'
11
13
  require 'more_core_extensions/core_ext/range'
12
14
  require 'more_core_extensions/core_ext/string'
13
15
  require 'more_core_extensions/core_ext/symbol'
@@ -6,14 +6,23 @@ module MoreCoreExtensions
6
6
  #
7
7
  # [1, [], nil].delete_nils # => [1, []]
8
8
  def delete_nils
9
- delete_if { |i| i.nil? }
9
+ delete_if(&:nil?)
10
10
  end
11
11
 
12
12
  # Deletes all items where the value is blank
13
13
  #
14
14
  # [1, [], nil].delete_blanks # => [1]
15
15
  def delete_blanks
16
- delete_if { |i| i.blank? }
16
+ delete_if(&:blank?)
17
+ end
18
+
19
+ # Deletes all keys and subkeys that match +key+.
20
+ #
21
+ # [{:a => {:b => 2, :c => 3}}].deep_delete(:b) # => [{:a => {:c => 3}}]
22
+ #
23
+ def deep_delete(key)
24
+ each { |i| i.deep_delete(key) if i.respond_to?(:deep_delete) }
25
+ self
17
26
  end
18
27
  end
19
28
  end
@@ -53,6 +53,9 @@ module MoreCoreExtensions
53
53
 
54
54
  private
55
55
 
56
+ ANSI_ESCAPE_SEQUENCE = /\e\[[^m]+m/.freeze
57
+ ANSI_RESET = "\e[0m".freeze
58
+
56
59
  def tableize_hashes
57
60
  # Convert the target to an Array of Arrays
58
61
  keys = options[:columns] || columns_from_hash_keys
@@ -102,7 +105,7 @@ module MoreCoreExtensions
102
105
  end
103
106
 
104
107
  def apply_width!(widths, field, field_i)
105
- widths[field_i] = [widths[field_i].to_i, field.to_s.length].max
108
+ widths[field_i] = [widths[field_i].to_i, ansi_strip(field.to_s).length].max
106
109
  widths[field_i] = [options[:max_width], widths[field_i].to_i].min if options[:max_width]
107
110
  end
108
111
 
@@ -118,13 +121,45 @@ module MoreCoreExtensions
118
121
  end
119
122
 
120
123
  def format_field(field, width, justification)
121
- field = field.to_s.gsub(/\n|\r/, '').slice(0, width)
124
+ field = field.to_s.gsub(/\n|\r/, '')
125
+ field = ansi_truncate(field, width)
126
+ width += ansi_escapes(field).sum { |f| f.to_s.size }
122
127
  "%0#{justification}#{width}s" % field
123
128
  end
124
129
 
130
+ def ansi_escapes?(field)
131
+ !!field.match(ANSI_ESCAPE_SEQUENCE)
132
+ end
133
+
134
+ def ansi_escapes(field)
135
+ field.to_enum(:scan, ANSI_ESCAPE_SEQUENCE).map { Regexp.last_match }
136
+ end
137
+
138
+ def ansi_strip(field)
139
+ field.gsub(ANSI_ESCAPE_SEQUENCE, '')
140
+ end
141
+
142
+ def ansi_truncate(field, width)
143
+ escapes = ansi_escapes(field)
144
+ if escapes.none?
145
+ field.slice(0, width)
146
+ else
147
+ escape_widths = 0
148
+ escapes.each do |e|
149
+ break if e.offset(0).first - escape_widths >= width
150
+
151
+ escape_widths += e[0].size
152
+ end
153
+
154
+ field = field.slice(0, width + escape_widths)
155
+ field << ANSI_RESET if ansi_escapes?(field) && !field.end_with?(ANSI_RESET)
156
+ field
157
+ end
158
+ end
159
+
125
160
  def format_table(table, widths)
126
161
  if options[:header] && table.size > 1
127
- header_separator = widths.collect { |w| "-" * (w + 2) }.join("+")
162
+ header_separator = widths.collect { |w| "-" * (w + 2) }.join("|")
128
163
  table.insert(1, header_separator)
129
164
  end
130
165
  table.join("\n") << "\n"
@@ -0,0 +1 @@
1
+ require 'more_core_extensions/core_ext/digest/uuid'
@@ -0,0 +1,26 @@
1
+ require 'active_support/core_ext/digest/uuid'
2
+
3
+ module Digest
4
+ module UUID
5
+ UUID_REGEX_FORMAT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.freeze
6
+
7
+ # Takes a UUID string of varying formats and cleans it. It will strip invalid characters,
8
+ # such as leading and trailing brackets as well as whitespace. The result is a lowercased,
9
+ # canonical UUID string.
10
+ #
11
+ # If the +guid+ argument is nil or blank, then nil is returned. If the +guid+ is already
12
+ # clean, then no additional cleaning occurs, and it is returned as-is.
13
+ #
14
+ # @param guid [String] A string that should more or less represent a UUID.
15
+ # @return [String] A lowercase v4 UUID string stripped of any extraneous characters.
16
+ #
17
+ def self.clean(guid)
18
+ return nil if guid.nil?
19
+ g = guid.to_s.downcase
20
+ return nil if g.strip.empty?
21
+ return g if g.length == 36 && g =~ UUID_REGEX_FORMAT
22
+ g.delete!('^0-9a-f')
23
+ g.sub!(/^([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})$/, '\1-\2-\3-\4-\5')
24
+ end
25
+ end
26
+ end
@@ -15,6 +15,16 @@ module MoreCoreExtensions
15
15
  def delete_blanks
16
16
  delete_if { |k, v| v.blank? }
17
17
  end
18
+
19
+ # Deletes all keys and subkeys that match +key+.
20
+ #
21
+ # {:a => {:b => 2, :c => 3}}.deep_delete(:b) # => {:a => {:c => 3}}
22
+ #
23
+ def deep_delete(key)
24
+ key = [key] unless key.kind_of?(Array)
25
+ key.each { |k| delete(k) }
26
+ each_value { |v| v.deep_delete(key) if v.respond_to?(:deep_delete) }
27
+ end
18
28
  end
19
29
  end
20
30
 
@@ -1,2 +1,3 @@
1
1
  require 'active_support/core_ext/object/blank'
2
+ require 'more_core_extensions/core_ext/object/deep_send'
2
3
  require 'more_core_extensions/core_ext/object/namespace'
@@ -0,0 +1,28 @@
1
+ module MoreCoreExtensions
2
+ module ObjectDeepSend
3
+ #
4
+ # Invokes the specified methods continuously, unless encountering a nil value.
5
+ #
6
+ # 10.deep_send("to_s.length") # => 2
7
+ # 10.deep_send("to_s", "length") # => 2
8
+ # 10.deep_send(:to_s, :length) # => 2
9
+ # 10.deep_send(["to_s", "length"]) # => 2
10
+ # [].deep_send("first.length") # => nil
11
+ #
12
+ def deep_send(*args)
13
+ args = args.first.dup if args.length == 1 && args.first.kind_of?(Array)
14
+ args = args.shift.to_s.strip.split('.') + args
15
+
16
+ arg = args.shift
17
+ raise ArgumentError if arg.nil?
18
+
19
+ result = send(arg)
20
+ return nil if result.nil?
21
+ return result if args.empty?
22
+
23
+ result.deep_send(args)
24
+ end
25
+ end
26
+ end
27
+
28
+ Object.send(:include, MoreCoreExtensions::ObjectDeepSend)
@@ -0,0 +1 @@
1
+ require 'more_core_extensions/core_ext/process/pause_resume'
@@ -0,0 +1,110 @@
1
+ module MoreCoreExtensions
2
+ module ProcessPauseResume
3
+ if Gem.win_platform?
4
+ require 'fiddle'
5
+ ntdll = Fiddle.dlopen('ntdll')
6
+ kernel32 = Fiddle.dlopen('kernel32')
7
+
8
+ NtSuspendProcess = Fiddle::Function.new(
9
+ ntdll['NtSuspendProcess'],
10
+ [Fiddle::TYPE_UINTPTR_T],
11
+ Fiddle::TYPE_INT
12
+ )
13
+
14
+ private_constant :NtSuspendProcess
15
+
16
+ NtResumeProcess = Fiddle::Function.new(
17
+ ntdll['NtResumeProcess'],
18
+ [Fiddle::TYPE_UINTPTR_T],
19
+ Fiddle::TYPE_INT
20
+ )
21
+
22
+ private_constant :NtResumeProcess
23
+
24
+ OpenProcess = Fiddle::Function.new(
25
+ kernel32['OpenProcess'],
26
+ [Fiddle::TYPE_LONG, Fiddle::TYPE_INT, Fiddle::TYPE_LONG],
27
+ Fiddle::TYPE_UINTPTR_T
28
+ )
29
+
30
+ private_constant :OpenProcess
31
+
32
+ CloseHandle = Fiddle::Function.new(
33
+ kernel32['CloseHandle'],
34
+ [Fiddle::TYPE_UINTPTR_T],
35
+ Fiddle::TYPE_INT
36
+ )
37
+
38
+ private_constant :CloseHandle
39
+
40
+ PROCESS_SUSPEND_RESUME = 0x00000800
41
+
42
+ private_constant :PROCESS_SUSPEND_RESUME
43
+ end
44
+
45
+ # Returns whether or not the given process is running.
46
+ #
47
+ def alive?(pid)
48
+ Process.kill(0, pid)
49
+ true
50
+ rescue Errno::ESRCH
51
+ false
52
+ end
53
+
54
+ # Suspend the process +pid+. If the process isn't running then this is no-op.
55
+ #
56
+ if Gem.win_platform?
57
+ def pause(pid)
58
+ return unless alive?(pid)
59
+
60
+ begin
61
+ handle = OpenProcess.call(PROCESS_SUSPEND_RESUME, 0, pid)
62
+
63
+ if handle == 0
64
+ raise SystemCallError, Fiddle.win32_last_error, "OpenProcess"
65
+ end
66
+
67
+ if NtSuspendProcess.call(handle) != 0
68
+ raise SystemCallError, Fiddle.win32_last_error, "NtSuspendProcess"
69
+ end
70
+ ensure
71
+ CloseHandle.call(handle) if handle
72
+ end
73
+ 1 # For cross-platform compatibility
74
+ end
75
+ else
76
+ def pause(pid)
77
+ Process.kill('STOP', pid) if alive?(pid)
78
+ end
79
+ end
80
+
81
+ # Resume the process +pid+. If the process isn't running then this is a no-op.
82
+ #
83
+ if Gem.win_platform?
84
+ def resume(pid)
85
+ return unless alive?(pid)
86
+
87
+ begin
88
+ handle = OpenProcess.call(PROCESS_SUSPEND_RESUME, 0, pid)
89
+
90
+ if handle == 0
91
+ raise SystemCallError, Fiddle.win32_last_error, "OpenProcess"
92
+ end
93
+
94
+ if NtResumeProcess.call(handle) != 0
95
+ raise SystemCallError, Fiddle.win32_last_error, "NtResumeProcess"
96
+ end
97
+ ensure
98
+ CloseHandle.call(handle) if handle
99
+ end
100
+ 1 # For cross-platform compatibility
101
+ end
102
+ else
103
+ def resume(pid)
104
+ Process.kill('CONT', pid) if alive?(pid)
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ Process.send(:extend, MoreCoreExtensions::ProcessPauseResume)
@@ -100,6 +100,21 @@ module MoreCoreExtensions
100
100
  end
101
101
  []
102
102
  end
103
+
104
+ # Create a deep clone of the object. This is similar to deep_dup
105
+ # but uses a Marshal based approach instead.
106
+ #
107
+ # h1 = {:a => "hello"}
108
+ # h2 = h1.deep_clone
109
+ #
110
+ # h1[:a] << " world"
111
+ #
112
+ # h1[:a] # "hello world"
113
+ # h2[:a] # "hello"
114
+ #
115
+ def deep_clone
116
+ Marshal.load(Marshal.dump(self))
117
+ end
103
118
  end
104
119
  end
105
120
  end
@@ -2,3 +2,4 @@ require 'more_core_extensions/core_ext/string/formats'
2
2
  require 'more_core_extensions/core_ext/string/hex_dump'
3
3
  require 'more_core_extensions/core_ext/string/iec60027_2'
4
4
  require 'more_core_extensions/core_ext/string/decimal_suffix'
5
+ require 'more_core_extensions/core_ext/string/to_i_with_method'
@@ -0,0 +1,87 @@
1
+ module MoreCoreExtensions
2
+ module StringToIWithMethod
3
+ NUMBER_WITH_METHOD_REGEX = /^([0-9\.,]+)\.([a-z]+)$/.freeze
4
+
5
+ # Converts to an Integer while also evaluating a method invocation
6
+ #
7
+ # This method is similar to #to_i, but does not support extraneous characters
8
+ # nor bases other than 10.
9
+ #
10
+ # "20".to_i_with_method # => 20
11
+ # "20.percent".to_i_with_method # => 20
12
+ # "20.megabytes".to_i_with_method # => 20_971_520
13
+ #
14
+ # "20.0".to_i_with_method # => 20
15
+ # "20.0.percent".to_i_with_method # => 20
16
+ # "20.0.megabytes".to_i_with_method # => 20_971_520
17
+ #
18
+ # 20.to_i_with_method # => 20
19
+ # 20.0.to_i_with_method # => 20
20
+ # nil.to_i_with_method # => 0
21
+ #
22
+ def to_i_with_method
23
+ to_x_with_method.to_i
24
+ end
25
+
26
+ # Converts to a Float while also evaluating a method invocation
27
+ #
28
+ # This method is similar to #to_f, but does not support extraneous characters.
29
+ #
30
+ # "20".to_f_with_method # => 20.0
31
+ # "20.percent".to_f_with_method # => 20.0
32
+ # "20.megabytes".to_f_with_method # => 20_971_520.0
33
+ #
34
+ # "20.1".to_f_with_method # => 20.1
35
+ # "20.1.percent".to_f_with_method # => 20.1
36
+ # "20.1.megabytes".to_f_with_method # => 21_076_377.6
37
+ #
38
+ # 20.to_f_with_method # => 20.0
39
+ # 20.1.to_f_with_method # => 20.1
40
+ # nil.to_f_with_method # => 0.0
41
+ #
42
+ def to_f_with_method
43
+ to_x_with_method.to_f
44
+ end
45
+
46
+ private def to_x_with_method
47
+ n = delete(',')
48
+ return n unless n =~ NUMBER_WITH_METHOD_REGEX && $2 != "percent"
49
+
50
+ n = $1.include?('.') ? $1.to_f : $1.to_i
51
+ n.public_send($2)
52
+ end
53
+
54
+ # Determines if the object contains a number with a method invocation
55
+ #
56
+ # "20".number_with_method? # => false
57
+ # "20.percent".number_with_method? # => true
58
+ # "20.0.percent".number_with_method? # => true
59
+ def number_with_method?
60
+ self =~ NUMBER_WITH_METHOD_REGEX
61
+ end
62
+ end
63
+
64
+ module NumericAndNilToIWithMethod
65
+ # See String#to_i_with_method
66
+ def to_i_with_method
67
+ to_i
68
+ end
69
+
70
+ # See String#to_f_with_method
71
+ def to_f_with_method
72
+ to_f
73
+ end
74
+ end
75
+
76
+ module ObjectToIWithMethod
77
+ # See String#number_with_method?
78
+ def number_with_method?
79
+ false
80
+ end
81
+ end
82
+ end
83
+
84
+ String.send(:prepend, MoreCoreExtensions::StringToIWithMethod)
85
+ Numeric.send(:prepend, MoreCoreExtensions::NumericAndNilToIWithMethod)
86
+ NilClass.send(:prepend, MoreCoreExtensions::NumericAndNilToIWithMethod)
87
+ Object.send(:prepend, MoreCoreExtensions::ObjectToIWithMethod)
@@ -1,3 +1,3 @@
1
1
  module MoreCoreExtensions
2
- VERSION = "4.0.0".freeze
2
+ VERSION = "4.3.1".freeze
3
3
  end
@@ -24,10 +24,12 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_development_dependency "bundler"
26
26
  spec.add_development_dependency "codeclimate-test-reporter"
27
+ spec.add_development_dependency "manageiq-style"
27
28
  spec.add_development_dependency "rake"
28
29
  spec.add_development_dependency "rspec", ">= 3.0"
29
30
  spec.add_development_dependency "simplecov"
30
31
  spec.add_development_dependency "timecop"
31
32
 
32
33
  spec.add_runtime_dependency "activesupport"
34
+ spec.add_runtime_dependency "sync"
33
35
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: more_core_extensions
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 4.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Frey
8
8
  - Brandon Dunne
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-01-31 00:00:00.000000000 Z
12
+ date: 2021-07-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -39,6 +39,20 @@ dependencies:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: manageiq-style
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
42
56
  - !ruby/object:Gem::Dependency
43
57
  name: rake
44
58
  requirement: !ruby/object:Gem::Requirement
@@ -109,6 +123,20 @@ dependencies:
109
123
  - - ">="
110
124
  - !ruby/object:Gem::Version
111
125
  version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: sync
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :runtime
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
112
140
  description: MoreCoreExtensions are a set of core extensions beyond those provided
113
141
  by ActiveSupport.
114
142
  email:
@@ -118,9 +146,11 @@ executables: []
118
146
  extensions: []
119
147
  extra_rdoc_files: []
120
148
  files:
149
+ - ".codeclimate.yml"
121
150
  - ".gitignore"
122
151
  - ".rspec"
123
152
  - ".rubocop.yml"
153
+ - ".rubocop_cc.yml"
124
154
  - ".rubocop_local.yml"
125
155
  - ".travis.yml"
126
156
  - CHANGELOG.md
@@ -148,6 +178,8 @@ files:
148
178
  - lib/more_core_extensions/core_ext/benchmark/realtime_store.rb
149
179
  - lib/more_core_extensions/core_ext/class.rb
150
180
  - lib/more_core_extensions/core_ext/class/hierarchy.rb
181
+ - lib/more_core_extensions/core_ext/digest.rb
182
+ - lib/more_core_extensions/core_ext/digest/uuid.rb
151
183
  - lib/more_core_extensions/core_ext/hash.rb
152
184
  - lib/more_core_extensions/core_ext/hash/deletes.rb
153
185
  - lib/more_core_extensions/core_ext/hash/nested.rb
@@ -162,7 +194,10 @@ files:
162
194
  - lib/more_core_extensions/core_ext/numeric/math.rb
163
195
  - lib/more_core_extensions/core_ext/numeric/rounding.rb
164
196
  - lib/more_core_extensions/core_ext/object.rb
197
+ - lib/more_core_extensions/core_ext/object/deep_send.rb
165
198
  - lib/more_core_extensions/core_ext/object/namespace.rb
199
+ - lib/more_core_extensions/core_ext/process.rb
200
+ - lib/more_core_extensions/core_ext/process/pause_resume.rb
166
201
  - lib/more_core_extensions/core_ext/range.rb
167
202
  - lib/more_core_extensions/core_ext/range/step_value.rb
168
203
  - lib/more_core_extensions/core_ext/shared/nested.rb
@@ -171,6 +206,7 @@ files:
171
206
  - lib/more_core_extensions/core_ext/string/formats.rb
172
207
  - lib/more_core_extensions/core_ext/string/hex_dump.rb
173
208
  - lib/more_core_extensions/core_ext/string/iec60027_2.rb
209
+ - lib/more_core_extensions/core_ext/string/to_i_with_method.rb
174
210
  - lib/more_core_extensions/core_ext/symbol.rb
175
211
  - lib/more_core_extensions/core_ext/symbol/to_i.rb
176
212
  - lib/more_core_extensions/version.rb
@@ -179,7 +215,7 @@ homepage: http://github.com/ManageIQ/more_core_extensions
179
215
  licenses:
180
216
  - MIT
181
217
  metadata: {}
182
- post_install_message:
218
+ post_install_message:
183
219
  rdoc_options: []
184
220
  require_paths:
185
221
  - lib
@@ -194,8 +230,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
194
230
  - !ruby/object:Gem::Version
195
231
  version: '0'
196
232
  requirements: []
197
- rubygems_version: 3.0.6
198
- signing_key:
233
+ rubygems_version: 3.1.4
234
+ signing_key:
199
235
  specification_version: 4
200
236
  summary: MoreCoreExtensions are a set of core extensions beyond those provided by
201
237
  ActiveSupport.