rearmed 1.3.1 → 2.0.0

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
- SHA1:
3
- metadata.gz: 8cd8b9873096a342bb640e7bab688970350bf050
4
- data.tar.gz: 84ac122091acba8d89b1c4f1b99bf2e9ff3896e2
2
+ SHA256:
3
+ metadata.gz: 5e9c5aa5c6b89f77aeae8704f39ad697f5fa90fcf2defb344b01e1a74374fe53
4
+ data.tar.gz: 50ab78b692722a964136b0e7ddfc6a2f4d0cf27f574fdc097e760d64ade52622
5
5
  SHA512:
6
- metadata.gz: 704335a6f2403d194b54bfbca86c6660d49f3c6a5eab6eb2031d813032e9c7d62ea7b03f35d11dd6a11adf251a6b15c706e39046e2fb298f093d2904e313ddd7
7
- data.tar.gz: d8d2552250bacd242eac8e83d492d6cde941a0177d4cbbc8888fececb7ffe568b7f336fa553bcc18746214dc02836744f3542aa34c998ba4694f8ea820e170fd
6
+ metadata.gz: 5faf458204002b2096d67c5eb0bdf79852cfe86a014ade04b6546a43516e45b441c1cd6dbc45738d4a196507c988841c9af2eca57bcdd6f08b67f401d44ce0a1
7
+ data.tar.gz: 3e825f05d3ff172f366845faa5eb44347c4f9b8110834cb915bb2bbd766db266618930f27446b3a2a803ca5b8e1b16ec728adc702911da85137eb935c5e267c1
@@ -1,6 +1,15 @@
1
1
  CHANGELOG
2
2
  ---------
3
3
 
4
+ - **2.0.0 - July 11, 2018**
5
+ - Rename all generic `Rearmed` methods to their respective object type subclass and add type checking. Three examples:
6
+ - `Rearmed.casecmp?(str1, str2)` changed to `Rearmed::String.casecmp?(str1, str2)`
7
+ - `Rearmed.hash_join(h)` changed to `Rearmed::Hash.join?(h)`
8
+ - `Rearmed.dig` is the only exception will remained at the global `Rearmed` namespace. This method is shared by both Array and Hash and also is used internally throughout the library.
9
+ - Change method of applying patches from `require 'rearmed/apply_patches'` to `Rearmed#apply_patches!`. Once `apply_patches!` has been called, then `enabled_patches` cannot be changed. If it is, it will raise a `PatchesAlreadyAppliedError`
10
+ - Overhaul `Rearmed#enabled_patches=` method with type checking
11
+ - Allow setting `:all` for `Rearmed#enabled_patches=`
12
+ - Add `Integer#length`, `Object#bool?`, `Object#true?`, `Object#false?`, `String#match?`. These methods were all borrowed from [`finishing_moves`](https://github.com/forgecrafted/finishing_moves), Thanks!
4
13
  - **1.3.1 - Sept 2, 2017**
5
14
  - Add `Enumerable#select_map`
6
15
  - Add `String#casecmp?` for Ruby 2.3.x and below
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
- # Rearmed Ruby <a href='https://travis-ci.org/westonganger/rearmed-rb' target='_blank'><img src='https://api.travis-ci.org/westonganger/rearmed-rb.svg?branch=master' border='0' alt='Build Status' /></a>
1
+ # Rearmed Ruby
2
2
 
3
- <a href='https://ko-fi.com/A5071NK' target='_blank'><img height='32' style='border:0px;height:32px;' src='https://az743702.vo.msecnd.net/cdn/kofi1.png?v=a' border='0' alt='Buy Me a Coffee' /></a>
3
+ <a href="https://badge.fury.io/rb/rearmed" target="_blank"><img height="21" style='border:0px;height:21px;' border='0' src="https://badge.fury.io/rb/rearmed.svg" alt="Gem Version"></a>
4
+ <a href='https://travis-ci.org/westonganger/rearmed-rb' target='_blank'><img height='21' style='border:0px;height:21px;' src='https://api.travis-ci.org/westonganger/rearmed-rb.svg?branch=master' border='0' alt='Build Status' /></a>
5
+ <a href='https://rubygems.org/gems/rearmed' target='_blank'><img height='21' style='border:0px;height:21px;' src='https://ruby-gem-downloads-badge.herokuapp.com/rearmed?label=rubygems&type=total&total_label=downloads&color=brightgreen' border='0' alt='RubyGems Downloads' /></a>
6
+ <a href='https://ko-fi.com/A5071NK' target='_blank'><img height='22' style='border:0px;height:22px;' src='https://az743702.vo.msecnd.net/cdn/kofi1.png?v=a' border='0' alt='Buy Me a Coffee' /></a>
4
7
 
5
8
  A collection of helpful methods and monkey patches for Arrays, Hash, Enumerables, Strings, Objects & Dates in Ruby. [Rearmed is a collection of plugins](https://github.com/westonganger?utf8=%E2%9C%93&tab=repositories&q=rearmed) which are driven by making life easier & coding more natural.
6
9
 
@@ -18,15 +21,15 @@ gem 'rearmed'
18
21
 
19
22
  # Usage
20
23
 
21
- ## Setup Enabled Monkey Patches (all are optional)
24
+ ## Setup Monkey Patches (all are opt-in)
22
25
 
23
26
  ```ruby
24
27
  # config/initializers/rearmed.rb
25
28
 
26
29
  Rearmed.enabled_patches = {
27
30
  array: {
28
- dig: false,
29
31
  delete_first: false,
32
+ dig: false,
30
33
  not_empty: false
31
34
  },
32
35
  date: {
@@ -44,14 +47,21 @@ Rearmed.enabled_patches = {
44
47
  only: false,
45
48
  to_struct: false
46
49
  },
50
+ integer: {
51
+ length: false
52
+ },
47
53
  object: {
54
+ bool?: false,
55
+ false?: false,
48
56
  in: false,
49
- not_nil: false
57
+ not_nil: false,
58
+ true?: false
50
59
  },
51
60
  string: {
52
61
  begins_with: false,
53
- casecmp?: false
62
+ casecmp?: false,
54
63
  ends_with: false,
64
+ match?: false,
55
65
  starts_with: false,
56
66
  to_bool: false,
57
67
  valid_float: false,
@@ -59,10 +69,34 @@ Rearmed.enabled_patches = {
59
69
  }
60
70
  }
61
71
 
72
+ Rearmed.apply_patches!
73
+ ```
74
+
75
+ Some other argument formats the `enabled_patches` option accepts are:
62
76
 
63
- require 'rearmed/apply_patches'
77
+ ```ruby
78
+ ### Enable everything
79
+ Rearmed.enabled_patches = :all
80
+
81
+ ### Disable everything
82
+ Rearmed.enabled_patches = nil
83
+
84
+ ### Hash values can be boolean/nil values also
85
+ Rearmed.enabled_patches = {
86
+ array: true,
87
+ date: {
88
+ now: true
89
+ },
90
+ enumerable: true,
91
+ hash: false,
92
+ integer: false,
93
+ object: nil,
94
+ string: nil
95
+ }
64
96
  ```
65
97
 
98
+ By design, once `Rearmed.apply_patches!` is called then `Rearmed.enabled_patches` is no longer editable and `Rearmed.apply_patches!` cannot be called again. If you try to do so, it will raise a `PatchesAlreadyAppliedError`. There is no-built in way of changing the patches, if you need to do so (which you shouldn't) that is up to you to figure out.
99
+
66
100
  ## Array Methods
67
101
  ```ruby
68
102
  array = [1,2,1,4,1]
@@ -133,6 +167,10 @@ my_var.not_nil?
133
167
  # Only monkey patched if not using ActiveSupport / Rails as this method is already defined there
134
168
  my_var.in?([1,2,3])
135
169
  my_var.in?(1,2,3) # or with splat arguments
170
+
171
+ my_var.bool? # if is true or false boolean value
172
+ my_var.true? # if is true boolean value
173
+ my_var.false? # if is false boolean value
136
174
  ```
137
175
 
138
176
  ## String
@@ -143,9 +181,14 @@ my_var.in?(1,2,3) # or with splat arguments
143
181
  '123.123'.valid_float?
144
182
  # or without monkey patch: Rearmed.valid_float?('123.123')
145
183
 
184
+ '123.123'.valid_number?
185
+ # or without monkey patch: Rearmed.valid_number?('123.123')
186
+
146
187
  'true'.to_bool
147
188
  # or without monkey patch: Rearmed.to_bool('true')
148
189
 
190
+ 'foo'.match?(/fo/) #=> true, this method returns a convenient boolean value instead of matchdata
191
+
149
192
  # alias of start_with? and end_with? to have more sensible method names
150
193
  'foo'.starts_with?('fo') # => true
151
194
  'foo'.begins_with?('fo') # => true
@@ -158,19 +201,19 @@ my_var.in?(1,2,3) # or with splat arguments
158
201
  ```
159
202
 
160
203
  # Contributing / Todo
161
- If you want to request a method please raise an issue and we can discuss the implementation.
162
-
163
- If you want to contribute here are a couple of things you could do:
204
+ If your looking to contribute here is a list of outstanding items:
164
205
 
165
206
  - Get the `natural_sort` method to accept a block
166
207
 
208
+ To request or add a method, please raise an issue and we can discuss the implementation.
209
+
167
210
 
168
211
  # Credits
169
212
  Created by Weston Ganger - [@westonganger](https://github.com/westonganger)
170
213
 
171
214
  For any consulting or contract work please contact me via my company website: [Solid Foundation Web Development](https://solidfoundationwebdev.com)
172
215
 
173
- ## Similar Libraries Created By Me
216
+ ## Other Libraries in the Rearmed family of Plugins
174
217
  - [Rearmed Rails](https://github.com/westonganger/rearmed_rails)
175
218
  - [Rearmed-JS](https://github.com/westonganger/rearmed-js)
176
219
  - [Rearmed-CSS](https://github.com/westonganger/rearmed-css)
data/Rakefile CHANGED
@@ -3,28 +3,19 @@ require 'bundler/gem_tasks'
3
3
 
4
4
  task :test do
5
5
  require 'rake/testtask'
6
+
6
7
  Rake::TestTask.new do |t|
7
8
  t.libs << 'test'
8
- t.test_files = FileList['test/**/tc_*.rb']
9
+ t.test_files = FileList['test/**/*_test.rb']
9
10
  t.verbose = true
10
11
  end
11
12
  end
12
13
 
13
14
  task :console do
14
15
  require 'rearmed'
15
- Rearmed.enabled_patches = {
16
- array: true,
17
- hash: true,
18
- object: true,
19
- string: true,
20
- date: true,
21
- enumerable: true,
22
- rails_3: true,
23
- rails_4: true,
24
- rails: true,
25
- minitest: true
26
- }
27
- require 'rearmed/apply_patches'
16
+
17
+ Rearmed.enabled_patches = :all
18
+ Rearmed.apply_patches!
28
19
 
29
20
  require 'irb'
30
21
  binding.irb
@@ -5,14 +5,63 @@ require 'rearmed/exceptions'
5
5
 
6
6
  module Rearmed
7
7
 
8
- @enabled_patches = eval(File.read(File.join(File.dirname(__FILE__), 'rearmed/default_enabled_patches.hash')))
8
+ DEFAULT_PATCHES = {
9
+ array: {},
10
+ date: {},
11
+ enumerable: {},
12
+ hash: {},
13
+ integer: {},
14
+ object: {},
15
+ string: {},
16
+ }.freeze
17
+ private_constant :DEFAULT_PATCHES
18
+
19
+ @enabled_patches = Marshal.load(Marshal.dump(DEFAULT_PATCHES))
20
+ @applied = false
9
21
 
10
22
  def self.enabled_patches=(val)
11
- @enabled_patches = val
23
+ if @applied
24
+ raise ::Rearmed::Exceptions::PatchesAlreadyAppliedError.new
25
+ else
26
+ if [nil, {}].include?(val)
27
+ @enabled_patches = Marshal.load(Marshal.dump(DEFAULT_PATCHES))
28
+ elsif val == :all
29
+ @enabled_patches = val
30
+ elsif val.is_a?(::Hash)
31
+ @enabled_patches = {}
32
+
33
+ DEFAULT_PATCHES.keys.each do |k|
34
+ methods = val[k] || val[k.to_sym]
35
+ if methods
36
+ if methods.is_a?(::Hash) || methods == true
37
+ @enabled_patches[k] = methods
38
+ else
39
+ raise TypeError.new('Invalid value within the hash passed to Rearmed.enabled_patches=')
40
+ end
41
+ else
42
+ @enabled_patches[k] = {}
43
+ end
44
+ end
45
+ else
46
+ raise TypeError.new('Invalid value passed to Rearmed.enabled_patches=')
47
+ end
48
+ end
12
49
  end
13
50
 
14
51
  def self.enabled_patches
15
52
  @enabled_patches
16
53
  end
17
54
 
55
+ def self.apply_patches!
56
+ if @applied
57
+ raise ::Rearmed::Exceptions::PatchesAlreadyAppliedError.new
58
+ else
59
+ Dir[File.join(__dir__, 'rearmed/monkey_patches/*.rb')].each do |filename|
60
+ require filename
61
+ end
62
+
63
+ @applied = true
64
+ end
65
+ end
66
+
18
67
  end
@@ -2,22 +2,28 @@ module Rearmed
2
2
  module Exceptions
3
3
 
4
4
  class BlockFoundError < StandardError
5
- def initialize(klass=nil)
5
+ def initialize
6
6
  super("Rearmed doesn't yet support a block on this method.")
7
7
  end
8
8
  end
9
9
 
10
10
  class NoArgOrBlockGivenError < StandardError
11
- def initialize(klass=nil)
11
+ def initialize
12
12
  super("Must pass an argument or a block.")
13
13
  end
14
14
  end
15
15
 
16
16
  class BothArgAndBlockError < StandardError
17
- def initialize(klass=nil)
17
+ def initialize
18
18
  super("Arguments and blocks must be used seperately.")
19
19
  end
20
20
  end
21
21
 
22
+ class PatchesAlreadyAppliedError < StandardError
23
+ def initialize
24
+ super("Cannot change or apply patches again after `Rearmed#apply_patches!` has been called.")
25
+ end
26
+ end
27
+
22
28
  end
23
29
  end
@@ -1,129 +1,181 @@
1
1
  module Rearmed
2
2
 
3
- def self.casecmp?(str1, str2)
4
- if str1.is_a?(String) && str2.is_a?(String)
5
- str1.casecmp(str2) == 0
6
- end
7
- end
8
-
9
3
  def self.dig(collection, *values)
10
- current_val = nil
11
- current_collection = collection
12
- values.each_with_index do |val,i|
13
- if i+1 == values.length
14
- if (current_collection.is_a?(Array) && val.is_a?(Integer)) || (current_collection.is_a?(Hash) && ['String','Symbol'].include?(val.class.name))
15
- current_val = current_collection[val]
16
- else
17
- current_val = nil
18
- end
19
- elsif current_collection.is_a?(Array)
20
- if val.is_a?(Integer)
21
- current_collection = current_collection[val]
22
- next
4
+ if collection.is_a?(::Hash) || collection.is_a?(::Array)
5
+ current_val = nil
6
+ current_collection = collection
7
+ values.each_with_index do |val,i|
8
+ if i+1 == values.length
9
+ if (current_collection.is_a?(::Array) && val.is_a?(::Integer)) || (current_collection.is_a?(::Hash) && [::String, ::Symbol].include?(val.class))
10
+ current_val = current_collection[val]
11
+ else
12
+ current_val = nil
13
+ end
14
+ elsif current_collection.is_a?(::Array)
15
+ if val.is_a?(::Integer)
16
+ current_collection = current_collection[val]
17
+ next
18
+ else
19
+ current_val = nil
20
+ break
21
+ end
22
+ elsif current_collection.is_a?(::Hash)
23
+ if [::String, ::Symbol].include?(val.class)
24
+ current_collection = current_collection[val]
25
+ next
26
+ else
27
+ current_val = nil
28
+ break
29
+ end
23
30
  else
24
31
  current_val = nil
25
- break
26
- end
27
- elsif current_collection.is_a?(Hash)
28
- if ['Symbol','String'].include?(val.class.name)
29
- current_collection = current_collection[val]
30
- next
31
- else
32
- current_val = nil
33
- break
32
+ break
34
33
  end
34
+ end
35
+
36
+ return current_val
37
+ else
38
+ raise TypeError.new("Invalid object passed to #{__method__}, must be a Hash or Array")
39
+ end
40
+ end
41
+
42
+ module Hash
43
+ def self.compact(hash)
44
+ if hash.is_a?(::Hash)
45
+ hash.reject{|_, value| value.nil?}
35
46
  else
36
- current_val = nil
37
- break
47
+ raise TypeError.new("Invalid object passed to #{__method__}, must be a Hash")
38
48
  end
39
49
  end
40
50
 
41
- return current_val
42
- end
51
+ def self.join(hash, delimiter=', ', &block)
52
+ if hash.is_a?(::Hash)
53
+ unless block_given?
54
+ block = ->(k,v){ "#{k}: #{v}" }
55
+ end
43
56
 
44
- def self.hash_compact(hash)
45
- hash.reject{|_, value| value.nil?}
46
- end
57
+ str = ""
47
58
 
48
- def self.hash_join(hash, delimiter=', ', &block)
49
- unless block_given?
50
- block = ->(k,v){ "#{k}: #{v}" }
51
- end
59
+ hash.each_with_index do |(k,v), i|
60
+ val = block.call(k,v)
61
+ unless val.is_a?(::String)
62
+ val = val.to_s
63
+ end
64
+ str << val
52
65
 
53
- str = ""
66
+ if i+1 < hash.length
67
+ str << delimiter
68
+ end
69
+ end
54
70
 
55
- hash.each_with_index do |(k,v), i|
56
- val = block.call(k,v)
57
- unless val.is_a?(String)
58
- val = val.to_s
71
+ return str
72
+ else
73
+ raise TypeError.new("Invalid object passed to #{__method__}, must be a Hash")
59
74
  end
60
- str << val
75
+ end
61
76
 
62
- if i+1 < hash.length
63
- str << delimiter
77
+ def self.only(hash, *keys)
78
+ if hash.is_a?(::Hash)
79
+ keys.map!{|key| hash.convert_key(key)} if hash.respond_to?(:convert_key, true)
80
+ keys.each_with_object(hash.class.new){|k, new_hash| new_hash[k] = hash[k] if hash.has_key?(k)}
81
+ else
82
+ raise TypeError.new("Invalid object passed to #{__method__}, must be a Hash")
64
83
  end
65
84
  end
66
85
 
67
- return str
68
- end
69
-
70
- def self.hash_only(hash, *keys)
71
- keys.map!{|key| hash.convert_key(key)} if hash.respond_to?(:convert_key, true)
72
- keys.each_with_object(hash.class.new){|k, new_hash| new_hash[k] = hash[k] if hash.has_key?(k)}
86
+ def self.to_struct(hash)
87
+ if hash.is_a?(::Hash)
88
+ Struct.new(*hash.keys).new(*hash.values)
89
+ else
90
+ raise TypeError.new("Invalid object passed to #{__method__}, must be a Hash")
91
+ end
92
+ end
73
93
  end
74
94
 
75
- def self.hash_to_struct(hash)
76
- Struct.new(*hash.keys).new(*hash.values)
77
- end
95
+ module Enumerable
96
+ def self.natural_sort_by(collection)
97
+ if collection.is_a?(::Enumerable)
98
+ collection.sort_by{|x| self._naturalize_str(yield(x))}
99
+ else
100
+ raise TypeError.new("Invalid object passed to #{__method__}, must be an Enumerable")
101
+ end
102
+ end
78
103
 
79
- def self.natural_sort_by(collection)
80
- collection.sort_by{|x| self.naturalize_str(yield(x))}
81
- end
104
+ def self.natural_sort(collection, options={})
105
+ if !collection.is_a?(::Enumerable)
106
+ raise TypeError.new("Invalid object passed to #{__method__}, must be an Enumerable")
107
+ elsif block_given?
108
+ Rearmed::Exceptions::BlockFoundError
109
+ else
110
+ collection.sort do |a,b|
111
+ if options[:reverse] == true
112
+ self._naturalize_str(b.to_s) <=> self._naturalize_str(a.to_s)
113
+ else
114
+ self._naturalize_str(a.to_s) <=> self._naturalize_str(b.to_s)
115
+ end
116
+ end
117
+ end
118
+ end
82
119
 
83
- def self.natural_sort(collection, options={})
84
- if block_given?
85
- Rearmed::Exceptions::BlockFoundError
86
- else
87
- collection.sort do |a,b|
88
- if options[:reverse] == true
89
- self.naturalize_str(b.to_s) <=> self.naturalize_str(a.to_s)
120
+ def self.select_map(collection)
121
+ if collection.is_a?(::Enumerable)
122
+ if block_given?
123
+ collection.select{|x| yield(x) }.map{|x| yield(x) }
90
124
  else
91
- self.naturalize_str(a.to_s) <=> self.naturalize_str(b.to_s)
125
+ collection.select.map
92
126
  end
127
+ else
128
+ raise TypeError.new("Invalid object passed to #{__method__}, must be an Enumerable")
93
129
  end
94
130
  end
95
- end
96
131
 
97
- def self.select_map(collection)
98
- if block_given?
99
- collection.select{|x| yield(x) }.map{|x| yield(x) }
100
- else
101
- collection.select.map
132
+ private
133
+
134
+ def self._naturalize_str(str)
135
+ str.to_s.split(/(\d+)/).map{|a| a =~ /\d+/ ? a.to_i : a}
102
136
  end
103
137
  end
104
138
 
105
- def self.to_bool(str)
106
- if str =~ /^(true|1|t|T)$/
107
- true
108
- elsif str =~ /^(false|0|f|F)$/
109
- false
110
- else
111
- nil
139
+ module String
140
+ def self.to_bool(str)
141
+ if str.is_a?(::String)
142
+ if str =~ /^(true|1|t|T)$/
143
+ true
144
+ elsif str =~ /^(false|0|f|F)$/
145
+ false
146
+ else
147
+ nil
148
+ end
149
+ else
150
+ raise TypeError.new("Invalid object passed to #{__method__}, must be a String")
151
+ end
112
152
  end
113
- end
114
153
 
115
- def self.valid_integer?(str)
116
- str =~ /^\d*$/ ? true : false
117
- end
154
+ def self.valid_integer?(str)
155
+ if str.is_a?(::String)
156
+ str =~ /^\d*$/ ? true : false
157
+ else
158
+ raise TypeError.new("Invalid object passed to #{__method__}")
159
+ end
160
+ end
118
161
 
119
- def self.valid_float?(str)
120
- str =~ /(^(\d+)(\.)?(\d+)?$)|(^(\d+)?(\.)(\d+)$)/ ? true : false
121
- end
162
+ def self.valid_float?(str)
163
+ if str.is_a?(::String)
164
+ str =~ /(^(\d+)(\.)?(\d+)?$)|(^(\d+)?(\.)(\d+)$)/ ? true : false
165
+ else
166
+ raise TypeError.new("Invalid object passed to #{__method__}, must be a String")
167
+ end
168
+ end
122
169
 
123
- private
124
-
125
- def self.naturalize_str(str)
126
- str.to_s.split(/(\d+)/).map{|a| a =~ /\d+/ ? a.to_i : a}
170
+ def self.casecmp?(str1, str2)
171
+ if str1.is_a?(::String)
172
+ if str2.is_a?(::String)
173
+ return str1.casecmp(str2) == 0
174
+ end
175
+ else
176
+ raise TypeError.new("Invalid object passed to #{__method__}, must be a String")
177
+ end
178
+ end
127
179
  end
128
180
 
129
181
  end