more_core_extensions 4.0.0 → 4.3.1

Sign up to get free protection for your applications and to get access to all the features.
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.