rearmed 1.2.0 → 1.2.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
  SHA1:
3
- metadata.gz: 270b7582528a427dfcd54ea2cbe616af8bc67717
4
- data.tar.gz: e97b0352883c108aa366ec3078bf188349e1b907
3
+ metadata.gz: d1c1c9a931a133791cfbdacdbfd5ccb01f50234d
4
+ data.tar.gz: 6daedcedcc902bfed66cad975fbcf99f34724163
5
5
  SHA512:
6
- metadata.gz: f4785d8f2332220c02dbe2d904ef328ff4554b98f6711c5e095a071beb52c6000ae540228c53f732beb9987e435c7d8c5820fb317d959fa4815b2f6e8247cf00
7
- data.tar.gz: 9f77a7b3b1e35f8027b00d676076e7e90ce33b88e34efdaa82b927c57b1caaa5e69bb8aa108b8b29c9f220911c45879d29f0dfa6d6df29d6d151cca0efec22dc
6
+ metadata.gz: 00253c513c5b1e4ba17485a1c7e72a2c5070e3e80121d8a612f5c8ebe10f06d04bff262bd117856a9fcffa0f1254e9fc9de5b50074bc61b126333e8a9be42624
7
+ data.tar.gz: c52b3d027600904d10d8ba89b3d9cb587ab6688c2b0c19a72fdb8b3d4766d177fc0d26d061283240ff86c277a515011bbb8c45c14a1409534492fb18d8aee341
@@ -1,7 +1,10 @@
1
1
  CHANGELOG
2
2
  ---------
3
3
 
4
- -
4
+ - **1.2.1 - Jan 24, 2017**
5
+ - Add Hash `join`, `to_struct`
6
+ - Fix `find_duplicates`
7
+ - Some minor refractoring
5
8
  - **1.2.0 - September 3, 2016**
6
9
  - Add Minitest patches `assert_changed` & `assert_not_changed`
7
10
  - Remove `dedupe` in favor of new `find_duplicates`
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Rearmed Ruby
2
2
  <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
3
 
4
- A collection of helpful methods and monkey patches for Objects, Strings, Enumerables, Arrays, Hash, Dates, Minitest & Rails
4
+ A collection of helpful methods and monkey patches for Objects, Strings, Enumerables, Arrays, Hash, Dates, Minitest & Rails (optional)
5
5
 
6
6
  The difference between this library and others is that all monkey patching is performed in an opt-in way because you shouldnt be using methods you dont know about anyways.
7
7
 
@@ -13,99 +13,89 @@ For applicable methods I have placed the implementation inside the Rearmed modul
13
13
  gem 'rearmed'
14
14
  ```
15
15
 
16
- Run `rails g rearmed:setup` to create a settings files in `config/initializers/rearmed.rb` where you can opt-in to the monkey patches available in the library. Set these values to true if you want to enable the applicable monkey patch.
16
+ Run `rails g rearmed:setup` to create a settings files in `config/initializers/rearmed.rb` where you can opt-in to the monkey patches available in the library. Set these values to true if you want to enable the applicable monkey patch. If your not using Rails then just copy config this into your file and start from there.
17
17
 
18
18
  ```ruby
19
19
  # config/initializers/rearmed.rb
20
20
 
21
21
  Rearmed.enabled_patches = {
22
- rails_4: {
23
- or: false,
24
- link_to_confirm: false
25
- },
26
- rails_3: {
27
- pluck: false,
28
- update_columns: false,
29
- all: false
30
- },
31
- rails: {
32
- pluck_to_hash: false,
33
- pluck_to_struct: false,
34
- find_or_create: false,
35
- find_duplicates: false,
36
- newest: false,
37
- reset_table: false,
38
- reset_auto_increment: false,
39
- find_relation_each: false,
40
- find_in_relation_batches: false,
41
- },
42
- string: {
43
- valid_integer: false,
44
- valid_float: false,
45
- to_bool: false,
46
- starts_with: false,
47
- begins_with: false,
48
- ends_with: false
49
- },
50
- hash: {
51
- only: false,
52
- dig: false,
53
- compact: false
54
- },
55
22
  array: {
56
23
  dig: false,
57
24
  delete_first: false,
58
25
  not_empty: false
59
26
  },
27
+ date: {
28
+ now: false
29
+ },
60
30
  enumerable: {
61
31
  natural_sort: false,
62
32
  natural_sort_by: false
63
33
  },
34
+ hash: {
35
+ compact: false,
36
+ dig: false,
37
+ join: false,
38
+ only: false,
39
+ to_struct: false
40
+ },
64
41
  object: {
65
42
  in: false,
66
43
  not_nil: false
67
44
  },
68
- date: {
69
- now: false
45
+ string: {
46
+ begins_with: false,
47
+ ends_with: false,
48
+ starts_with: false,
49
+ to_bool: false,
50
+ valid_float: false,
51
+ valid_integer: false
70
52
  },
71
53
  minitest: {
72
54
  assert_changed: false,
73
55
  assert_not_changed: false
56
+ },
57
+ rails: {
58
+ find_duplicates: false,
59
+ find_in_relation_batches: false,
60
+ find_or_create: false,
61
+ find_relation_each: false,
62
+ newest: false,
63
+ pluck_to_hash: false,
64
+ pluck_to_struct: false,
65
+ reset_auto_increment: false,
66
+ reset_table: false
67
+ },
68
+ rails_4: {
69
+ link_to_confirm: false,
70
+ or: false
71
+ },
72
+ rails_3: {
73
+ all: false,
74
+ pluck: false,
75
+ update_columns: false
74
76
  }
75
77
  }
76
78
 
77
- require 'rearmed/apply_patches'
78
- ```
79
79
 
80
- ### Object
81
- ```ruby
82
- my_var.not_nil?
83
-
84
- # Only for non-Rails environments, as Rails already has this method
85
- my_var.in?([1,2,3])
86
- my_var.in?(1,2,3) # or with splat arguments
80
+ require 'rearmed/apply_patches'
87
81
  ```
88
82
 
89
- ### String
83
+ ### Array Methods
90
84
  ```ruby
91
- '123'.valid_integer?
92
- # or without monkey patch: Rearmed.valid_integer?('123')
93
-
94
- '123.123'.valid_float?
95
- # or without monkey patch: Rearmed.valid_float?('123.123')
96
-
97
- 'true'.to_bool
98
- # or without monkey patch: Rearmed.to_bool('true')
85
+ array = [1,2,1,4,1]
86
+ array.delete_first(1) # => 1
87
+ puts array #=> [2,1,4,1]
88
+ array.delete_first{|x| 1 == x} # => 1
89
+ puts array # => [2,4,1]
90
+ array.delete_first # => 2
91
+ puts array # => [4,1]
99
92
 
100
- # alias of start_with? and end_with? to have more sensible method names
101
- 'foo'.starts_with?('fo') # => true
102
- 'foo'.begins_with?('fo') # => true
103
- 'bar'.ends_with?('ar') # => true
104
- ```
93
+ array.not_empty? # => true
105
94
 
106
- ### Date
107
- ```ruby
108
- Date.now
95
+ # Only available on array and hash in Ruby 2.2.x or below
96
+ items = [{foo: ['foo','bar']}, {test: 'thing'}]
97
+ items.dig(0, :foo, 1) # => 'bar'
98
+ # or without monkey patch: Rearmed.dig(items, 0, :foo, 1)
109
99
  ```
110
100
 
111
101
  ### Enumerable Methods (Array, Hash, etc.)
@@ -118,6 +108,27 @@ items.natural_sort(reverse: true) # because natural_sort does not accept a block
118
108
  items = [{version: "1.1"}, {version: "1.11"}, {version: "1.2"}]
119
109
  items.natural_sort_by{|x| x[:version]}
120
110
  # or without monkey patch: Rearmed.natural_sort_by(items){|x| x[:version]}
111
+ ```
112
+
113
+ ### Date
114
+ ```ruby
115
+ Date.now
116
+ ```
117
+
118
+ ### Hash Methods
119
+ ```ruby
120
+ my_hash.compact
121
+ my_hash.compact!
122
+
123
+ hash.join{|k,v| "#{k}: #{v}\n"}
124
+
125
+ hash = {foo: 'foo', bar: 'bar', other: 'other'}
126
+ hash.only(:foo, :bar) # => {foo: 'foo'}
127
+ # or without monkey patch: Rearmed.only(hash, :foo, :bar)
128
+
129
+ hash.only!(:foo, :bar)
130
+
131
+ hash.to_struct
121
132
 
122
133
  # Only available on array and hash in Ruby 2.2.x or below
123
134
  items = [{foo: ['foo','bar']}, {test: 'thing'}]
@@ -125,29 +136,45 @@ items.dig(0, :foo, 1) # => 'bar'
125
136
  # or without monkey patch: Rearmed.dig(items, 0, :foo, 1)
126
137
  ```
127
138
 
128
- ### Array Methods
139
+ ### Object
129
140
  ```ruby
130
- array = [1,2,1,4,1]
131
- array.delete_first(1) # => 1
132
- puts array #=> [2,1,4,1]
133
- array.delete_first{|x| 1 == x} # => 1
134
- puts array # => [2,4,1]
135
- array.delete_first # => 2
136
- puts array # => [4,1]
141
+ my_var.not_nil?
137
142
 
138
- array.not_empty? # => true
143
+ # Only for non-Rails environments, as Rails already has this method
144
+ my_var.in?([1,2,3])
145
+ my_var.in?(1,2,3) # or with splat arguments
139
146
  ```
140
147
 
141
- ### Hash Methods
148
+ ### String
142
149
  ```ruby
143
- hash = {foo: 'foo', bar: 'bar', other: 'other'}
144
- hash.only(:foo, :bar) # => {foo: 'foo'}
145
- # or without monkey patch: Rearmed.only(hash, :foo, :bar)
150
+ '123'.valid_integer?
151
+ # or without monkey patch: Rearmed.valid_integer?('123')
146
152
 
147
- hash.only!(:foo, :bar)
153
+ '123.123'.valid_float?
154
+ # or without monkey patch: Rearmed.valid_float?('123.123')
148
155
 
149
- my_hash.compact
150
- my_hash.compact!
156
+ 'true'.to_bool
157
+ # or without monkey patch: Rearmed.to_bool('true')
158
+
159
+ # alias of start_with? and end_with? to have more sensible method names
160
+ 'foo'.starts_with?('fo') # => true
161
+ 'foo'.begins_with?('fo') # => true
162
+ 'bar'.ends_with?('ar') # => true
163
+ ```
164
+
165
+ ### Minitest Methods
166
+ ```ruby
167
+ assert_changed 'user.name' do
168
+ user.name = "Bob"
169
+ end
170
+
171
+ assert_not_changed -> { user.name } do
172
+ user.update(user_params)
173
+ end
174
+
175
+ assert_not_changed lambda{ user.name } do
176
+ user.update(user_params)
177
+ end
151
178
  ```
152
179
 
153
180
  ### Rails
@@ -189,13 +216,15 @@ Post.find_relation_each # this returns a relation instead of an array
189
216
 
190
217
  ##### Rails 4.x Backports
191
218
  ```ruby
219
+ # returns to rails 3 behaviour of allowing confirm attribute as well as data-confirm
220
+ = link_to 'Delete', post_path(post), method: :delete, confirm: "Are you sure you want to delete this post?"
221
+
222
+ # This version of `or` behaves way nicer than the one implemented in Rails 5, it allows you to do what you need.
223
+ # However this patch does not work in Rails 5+
192
224
  Post.where(name: 'foo').or.where(content: 'bar')
193
225
  Post.where(name: 'foo').or.my_custom_scope
194
226
  Post.where(name: 'foo').or(Post.where(content: 'bar'))
195
227
  Post.where(name: 'foo).or(content: 'bar')
196
-
197
- = link_to 'Delete', post_path(post), method: :delete, confirm: "Are you sure you want to delete this post?"
198
- # returns to rails 3 behaviour of allowing confirm attribute as well as data-confirm
199
228
  ```
200
229
 
201
230
  ##### Rails 3.x Backports
@@ -208,21 +237,6 @@ my_hash.compact # See Hash methods above
208
237
  my_hash.compact!
209
238
  ```
210
239
 
211
- ### Minitest Method
212
- ```ruby
213
- assert_changed 'user.name' do
214
- user.name = "Bob"
215
- end
216
-
217
- assert_not_changed -> { user.name } do
218
- user.update(user_params)
219
- end
220
-
221
- assert_not_changed lambda{ user.name } do
222
- user.update(user_params)
223
- end
224
- ```
225
-
226
240
  # Contributing / Todo
227
241
  If you want to request a method please raise an issue and we can discuss the implementation.
228
242
 
@@ -230,7 +244,6 @@ If you want to contribute here are a couple of things you could do:
230
244
 
231
245
  - Add Tests for Rails methods
232
246
  - Get the `natural_sort` method to accept a block
233
- - Get the `assert_changed` and `assert_not_changed` method to accept a String with the variable name similar to Rails ``
234
247
 
235
248
 
236
249
  # Credits
data/Rakefile CHANGED
@@ -10,4 +10,24 @@ task :test do
10
10
  end
11
11
  end
12
12
 
13
+ task :console do
14
+ 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'
28
+
29
+ require 'irb'
30
+ binding.irb
31
+ end
32
+
13
33
  task default: :test
@@ -5,61 +5,7 @@ module Rearmed
5
5
 
6
6
  def setup
7
7
  create_file "config/initializers/rearmed.rb", <<eos
8
- Rearmed.enabled_patches = {
9
- rails_4: {
10
- or: false,
11
- link_to_confirm: false
12
- },
13
- rails_3: {
14
- pluck: false,
15
- update_columns: false,
16
- all: false
17
- },
18
- rails: {
19
- pluck_to_hash: false,
20
- pluck_to_struct: false,
21
- find_or_create: false,
22
- find_duplicates: false,
23
- newest: false,
24
- reset_table: false,
25
- reset_auto_increment: false,
26
- find_relation_each: false,
27
- find_in_relation_batches: false,
28
- },
29
- string: {
30
- valid_integer: false,
31
- valid_float: false,
32
- to_bool: false,
33
- starts_with: false,
34
- begins_with: false,
35
- ends_with: false,
36
- },
37
- hash: {
38
- only: false,
39
- dig: false,
40
- compact: false,
41
- },
42
- array: {
43
- dig: false,
44
- delete_first: false,
45
- not_empty: false
46
- },
47
- enumerable: {
48
- natural_sort: false,
49
- natural_sort_by: false
50
- },
51
- object: {
52
- in: false,
53
- not_nil: false
54
- },
55
- date: {
56
- now: false
57
- },
58
- minitest: {
59
- assert_changed: false,
60
- assert_not_changed: false
61
- }
62
- }
8
+ Rearmed.enabled_patches = #{File.read(File.join(File.dirname(__FILE__), '../../rearmed/default_enabled_patches.hash'))}
63
9
 
64
10
  require 'rearmed/apply_patches'
65
11
  eos
@@ -1,59 +1,11 @@
1
+ require 'rearmed/version'
2
+
3
+ require 'rearmed/methods'
4
+ require 'rearmed/exceptions'
5
+
1
6
  module Rearmed
2
7
 
3
- @enabled_patches = {
4
- rails_4: {
5
- or: false,
6
- link_to_confirm: false
7
- },
8
- rails_3: {
9
- pluck: false,
10
- update_columns: false,
11
- all: false
12
- },
13
- rails: {
14
- pluck_to_hash: false,
15
- pluck_to_struct: false,
16
- find_or_create: false,
17
- find_duplicates: false,
18
- reset_table: false,
19
- reset_auto_increment: false,
20
- find_relation_each: false,
21
- find_in_relation_batches: false,
22
- },
23
- string: {
24
- valid_integer: false,
25
- valid_float: false,
26
- to_bool: false,
27
- starts_with: false,
28
- begins_with: false,
29
- ends_with: false
30
- },
31
- hash: {
32
- only: false,
33
- dig: false,
34
- compact: false
35
- },
36
- array: {
37
- dig: false,
38
- delete_first: false,
39
- not_empty: false
40
- },
41
- enumerable: {
42
- natural_sort: false,
43
- natural_sort_by: false
44
- },
45
- object: {
46
- in: false,
47
- not_nil: false
48
- },
49
- date: {
50
- now: false
51
- },
52
- minitest: {
53
- assert_changed: false,
54
- assert_not_changed: false
55
- }
56
- }
8
+ @enabled_patches = eval(File.read(File.join(File.dirname(__FILE__), 'rearmed/default_enabled_patches.hash')))
57
9
 
58
10
  def self.enabled_patches=(val)
59
11
  @enabled_patches = val
@@ -63,105 +15,4 @@ module Rearmed
63
15
  @enabled_patches
64
16
  end
65
17
 
66
- def self.valid_integer?(str)
67
- str =~ /^\d*$/ ? true : false
68
- end
69
-
70
- def self.valid_float?(str)
71
- str =~ /(^(\d+)(\.)?(\d+)?$)|(^(\d+)?(\.)(\d+)$)/ ? true : false
72
- end
73
-
74
- def self.to_bool(str)
75
- if str =~ /^true$/
76
- true
77
- elsif str =~ /^false$/
78
- false
79
- else
80
- #raise(ArgumentError.new "incorrect element #{str}")
81
- nil
82
- end
83
- end
84
-
85
- def self.natural_sort_by(array)
86
- array.sort_by{|x| self.naturalize_str(yield(x))}
87
- end
88
-
89
- def self.natural_sort(array, options={})
90
- if block_given?
91
- BlockFoundError
92
- else
93
- array.sort do |a,b|
94
- if options[:reverse] == true
95
- self.naturalize_str(b.to_s) <=> self.naturalize_str(a.to_s)
96
- else
97
- self.naturalize_str(a.to_s) <=> self.naturalize_str(b.to_s)
98
- end
99
- end
100
- end
101
- end
102
-
103
- def self.only(hash, *keys)
104
- keys.map!{|key| hash.convert_key(key)} if hash.respond_to?(:convert_key, true)
105
- keys.each_with_object(hash.class.new){|k, new_hash| new_hash[k] = hash[k] if hash.has_key?(k)}
106
- end
107
-
108
- def self.dig(collection, *values)
109
- current_val = nil
110
- current_collection = collection
111
- values.each_with_index do |val,i|
112
- if i+1 == values.length
113
- if (current_collection.is_a?(Array) && val.is_a?(Integer)) || (current_collection.is_a?(Hash) && ['String','Symbol'].include?(val.class.name))
114
- current_val = current_collection[val]
115
- else
116
- current_val = nil
117
- end
118
- elsif current_collection.is_a?(Array)
119
- if val.is_a?(Integer)
120
- current_collection = current_collection[val]
121
- next
122
- else
123
- current_val = nil
124
- break
125
- end
126
- elsif current_collection.is_a?(Hash)
127
- if ['Symbol','String'].include?(val.class.name)
128
- current_collection = current_collection[val]
129
- next
130
- else
131
- current_val = nil
132
- break
133
- end
134
- else
135
- current_val = nil
136
- break
137
- end
138
- end
139
-
140
- return current_val
141
- end
142
-
143
- class BlockFoundError < StandardError
144
- def initialize(klass=nil)
145
- super("Rearmed doesn't yet support a block on this method.")
146
- end
147
- end
148
-
149
- class NoArgOrBlockGivenError < StandardError
150
- def initialize(klass=nil)
151
- super("Must pass an argument or a block.")
152
- end
153
- end
154
-
155
- class BothArgAndBlockError < StandardError
156
- def initialize(klass=nil)
157
- super("Arguments and blocks must be used seperately.")
158
- end
159
- end
160
-
161
- private
162
-
163
- def self.naturalize_str(str)
164
- str.to_s.split(/(\d+)/).map{|a| a =~ /\d+/ ? a.to_i : a}
165
- end
166
-
167
18
  end
@@ -0,0 +1,57 @@
1
+ {
2
+ array: {
3
+ dig: false,
4
+ delete_first: false,
5
+ not_empty: false
6
+ },
7
+ date: {
8
+ now: false
9
+ },
10
+ enumerable: {
11
+ natural_sort: false,
12
+ natural_sort_by: false
13
+ },
14
+ hash: {
15
+ compact: false,
16
+ dig: false,
17
+ join: false,
18
+ only: false,
19
+ to_struct: false
20
+ },
21
+ object: {
22
+ in: false,
23
+ not_nil: false
24
+ },
25
+ string: {
26
+ begins_with: false,
27
+ ends_with: false,
28
+ starts_with: false,
29
+ to_bool: false,
30
+ valid_float: false,
31
+ valid_integer: false
32
+ },
33
+ minitest: {
34
+ assert_changed: false,
35
+ assert_not_changed: false
36
+ },
37
+ rails: {
38
+ find_duplicates: false,
39
+ find_in_relation_batches: false,
40
+ find_or_create: false,
41
+ find_relation_each: false,
42
+ newest: false,
43
+ pluck_to_hash: false,
44
+ pluck_to_struct: false,
45
+ reset_auto_increment: false,
46
+ reset_table: false
47
+ },
48
+ rails_4: {
49
+ link_to_confirm: false,
50
+ or: false
51
+ },
52
+ rails_3: {
53
+ all: false,
54
+ pluck: false,
55
+ update_columns: false
56
+ }
57
+ }
@@ -0,0 +1,23 @@
1
+ module Rearmed
2
+ module Exceptions
3
+
4
+ class BlockFoundError < StandardError
5
+ def initialize(klass=nil)
6
+ super("Rearmed doesn't yet support a block on this method.")
7
+ end
8
+ end
9
+
10
+ class NoArgOrBlockGivenError < StandardError
11
+ def initialize(klass=nil)
12
+ super("Must pass an argument or a block.")
13
+ end
14
+ end
15
+
16
+ class BothArgAndBlockError < StandardError
17
+ def initialize(klass=nil)
18
+ super("Arguments and blocks must be used seperately.")
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,109 @@
1
+ module Rearmed
2
+
3
+ def self.dig(collection, *values)
4
+ current_val = nil
5
+ current_collection = collection
6
+ values.each_with_index do |val,i|
7
+ if i+1 == values.length
8
+ if (current_collection.is_a?(Array) && val.is_a?(Integer)) || (current_collection.is_a?(Hash) && ['String','Symbol'].include?(val.class.name))
9
+ current_val = current_collection[val]
10
+ else
11
+ current_val = nil
12
+ end
13
+ elsif current_collection.is_a?(Array)
14
+ if val.is_a?(Integer)
15
+ current_collection = current_collection[val]
16
+ next
17
+ else
18
+ current_val = nil
19
+ break
20
+ end
21
+ elsif current_collection.is_a?(Hash)
22
+ if ['Symbol','String'].include?(val.class.name)
23
+ current_collection = current_collection[val]
24
+ next
25
+ else
26
+ current_val = nil
27
+ break
28
+ end
29
+ else
30
+ current_val = nil
31
+ break
32
+ end
33
+ end
34
+
35
+ return current_val
36
+ end
37
+
38
+ def self.join(hash, delimiter=', ', &block)
39
+ unless block_given?
40
+ block = -> (k,v) {
41
+ "#{k}: #{v}"
42
+ }
43
+ end
44
+
45
+ str = ""
46
+
47
+ hash.each_with_index do |(k,v), i|
48
+ val = block.call(k,v)
49
+ unless val.is_a?(String)
50
+ val = val.to_s
51
+ end
52
+ str << val
53
+
54
+ if i+1 < hash.length
55
+ str << delimiter
56
+ end
57
+ end
58
+
59
+ return str
60
+ end
61
+
62
+ def self.natural_sort_by(array)
63
+ array.sort_by{|x| self.naturalize_str(yield(x))}
64
+ end
65
+
66
+ def self.natural_sort(array, options={})
67
+ if block_given?
68
+ Rearmed::Exceptions::BlockFoundError
69
+ else
70
+ array.sort do |a,b|
71
+ if options[:reverse] == true
72
+ self.naturalize_str(b.to_s) <=> self.naturalize_str(a.to_s)
73
+ else
74
+ self.naturalize_str(a.to_s) <=> self.naturalize_str(b.to_s)
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ def self.only(hash, *keys)
81
+ keys.map!{|key| hash.convert_key(key)} if hash.respond_to?(:convert_key, true)
82
+ keys.each_with_object(hash.class.new){|k, new_hash| new_hash[k] = hash[k] if hash.has_key?(k)}
83
+ end
84
+
85
+ def self.to_bool(str)
86
+ if str =~ /^(true|1|t|T)$/
87
+ true
88
+ elsif str =~ /^(false|0|f|F)$/
89
+ false
90
+ else
91
+ nil
92
+ end
93
+ end
94
+
95
+ def self.valid_integer?(str)
96
+ str =~ /^\d*$/ ? true : false
97
+ end
98
+
99
+ def self.valid_float?(str)
100
+ str =~ /(^(\d+)(\.)?(\d+)?$)|(^(\d+)?(\.)(\d+)$)/ ? true : false
101
+ end
102
+
103
+ private
104
+
105
+ def self.naturalize_str(str)
106
+ str.to_s.split(/(\d+)/).map{|a| a =~ /\d+/ ? a.to_i : a}
107
+ end
108
+
109
+ end
@@ -10,7 +10,7 @@ Array.module_eval do
10
10
  if array_enabled || Rearmed.dig(Rearmed.enabled_patches, :array, :delete_first)
11
11
  def delete_first(item=(no_arg_passed = true; nil))
12
12
  if block_given? && !no_arg_passed
13
- raise BothArgAndBlockError
13
+ raise Rearmed::Exceptions::BothArgAndBlockError
14
14
  elsif block_given?
15
15
  self.delete_at(self.index{|x| yield(x)} || self.length)
16
16
  elsif item || !no_arg_passed
@@ -12,6 +12,22 @@ Hash.class_eval do
12
12
  end
13
13
  end
14
14
 
15
+ if RUBY_VERSION.to_f < 2.3 && hash_enabled || Rearmed.dig(Rearmed.enabled_patches, :hash, :dig)
16
+ def dig(*args)
17
+ Rearmed.dig(self, *args)
18
+ end
19
+ end
20
+
21
+ if hash_enabled || Rearmed.dig(Rearmed.enabled_patches, :hash, :join)
22
+ def join(delimiter=', ', &block)
23
+ if block_given?
24
+ Rearmed.join(self, delimiter, &block)
25
+ else
26
+ Rearmed.join(self, delimiter)
27
+ end
28
+ end
29
+ end
30
+
15
31
  if hash_enabled || Rearmed.dig(Rearmed.enabled_patches, :hash, :only)
16
32
  def only(*keys)
17
33
  Rearmed.only(self, *keys)
@@ -26,9 +42,9 @@ Hash.class_eval do
26
42
  end
27
43
  end
28
44
 
29
- if RUBY_VERSION.to_f < 2.3 && hash_enabled || Rearmed.dig(Rearmed.enabled_patches, :hash, :dig)
30
- def dig(*args)
31
- Rearmed.dig(self, *args)
45
+ if hash_enabled || Rearmed.dig(Rearmed.enabled_patches, :hash, :to_struct)
46
+ def to_struct
47
+ Struct.new(*keys).new(*values)
32
48
  end
33
49
  end
34
50
  end
@@ -87,8 +87,8 @@ if defined?(ActiveRecord)
87
87
  end
88
88
 
89
89
  options[:columns] ||= self.column_names.reject{|x| [self.primary_key, :created_at, :updated_at, :deleted_at].include?(x)}
90
-
91
- ids = self.select("MIN(#{self.primary_key}) as #{self.primary_key}").group(options[:columns]).pluck(self.primary_key)
90
+
91
+ duplicates = self.select("#{options[:columns].join(', ')}, COUNT(*)").group(options[:columns]).having("COUNT(*) > 1")
92
92
 
93
93
  if options[:delete]
94
94
  if options[:delete] == true
@@ -101,9 +101,26 @@ if defined?(ActiveRecord)
101
101
  end
102
102
  end
103
103
 
104
- duplicates = self.where.not(self.primary_key => ids)
104
+ if options[:delete][:keep] == :last
105
+ duplicates.reverse!
106
+ end
107
+
108
+ used = []
109
+ duplicates.reject! do |x|
110
+ attrs = x.attributes.slice(*options[:columns].collect(&:to_s))
111
+
112
+ if used.include?(attrs)
113
+ return false
114
+ else
115
+ used.push attrs
116
+ return true
117
+ end
118
+ end
119
+ used = nil
105
120
 
106
121
  if options[:delete][:delete_method].to_sym == :delete
122
+ duplicates = self.where(id: duplicates.collect(&:id))
123
+
107
124
  if x.respond_to?(:delete_all!)
108
125
  duplicates.delete_all!
109
126
  else
@@ -120,7 +137,7 @@ if defined?(ActiveRecord)
120
137
  end
121
138
  return nil
122
139
  else
123
- return self.where.not(self.primary_key => ids)
140
+ return duplicates
124
141
  end
125
142
  end
126
143
  end
@@ -222,7 +239,7 @@ if defined?(ActiveRecord)
222
239
  while records.any?
223
240
  records_size = records.size
224
241
  primary_key_offset = records.last.id
225
- raise "Primary key not included in the custom select clause" unless primary_key_offset
242
+ raise ActiveRecordError, "Primary key not included in the custom select clause" unless primary_key_offset
226
243
 
227
244
  yield records
228
245
 
@@ -51,7 +51,7 @@ if defined?(ActiveRecord)
51
51
  while records.any?
52
52
  records_size = records.size
53
53
  primary_key_offset = records.last.id
54
- raise "Primary key not included in the custom select clause" unless primary_key_offset
54
+ raise ActiveRecordError, "Primary key not included in the custom select clause" unless primary_key_offset
55
55
 
56
56
  yield records
57
57
 
@@ -1,3 +1,3 @@
1
1
  module Rearmed
2
- VERSION = "1.2.0"
2
+ VERSION = "1.2.1"
3
3
  end
@@ -137,13 +137,28 @@ class TestRearmed < MiniTest::Test
137
137
  hash = {foo: 'foo', bar: 'bar', other: 'other'}
138
138
  eql(Rearmed.only(hash, :foo, :bar), {foo: 'foo', bar: 'bar'})
139
139
 
140
-
141
140
  hash = {foo: nil, bar: nil, other: 'other'}
142
141
  eql(hash.compact, {other: 'other'})
143
142
 
144
143
  hash = {foo: nil, bar: nil, other: 'other'}
145
144
  hash.compact!
146
145
  eql(hash, {other: 'other'})
146
+
147
+ hash = {foo: :bar, bar: :foo}
148
+ eql(hash.join, "foo: bar, bar: foo")
149
+ eql(hash.join('___'), "foo: bar___bar: foo")
150
+ eql(hash.join{|k,v| v}, "bar, foo")
151
+ eql(hash.join('___'){|k,v| v}, "bar___foo")
152
+ eql(Rearmed.join(hash), "foo: bar, bar: foo")
153
+ eql(Rearmed.join(hash, '___'), "foo: bar___bar: foo")
154
+ eql(Rearmed.join(hash){|k,v| v}, "bar, foo")
155
+ eql(Rearmed.join(hash, '___'){|k,v| v}, "bar___foo")
156
+
157
+ hash = {foo: :bar, bar: 'foo'}
158
+ struct = hash.to_struct
159
+ assert(struct.is_a?(Struct))
160
+ eql(struct.foo, :bar)
161
+ eql(struct.bar, 'foo')
147
162
  end
148
163
 
149
164
  def test_object
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rearmed
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Weston Ganger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-03 00:00:00.000000000 Z
11
+ date: 2017-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -66,6 +66,9 @@ files:
66
66
  - lib/generators/rearmed/setup_generator.rb
67
67
  - lib/rearmed.rb
68
68
  - lib/rearmed/apply_patches.rb
69
+ - lib/rearmed/default_enabled_patches.hash
70
+ - lib/rearmed/exceptions.rb
71
+ - lib/rearmed/methods.rb
69
72
  - lib/rearmed/monkey_patches/array.rb
70
73
  - lib/rearmed/monkey_patches/date.rb
71
74
  - lib/rearmed/monkey_patches/enumerable.rb
@@ -97,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
97
100
  version: '0'
98
101
  requirements: []
99
102
  rubyforge_project:
100
- rubygems_version: 2.5.1
103
+ rubygems_version: 2.6.8
101
104
  signing_key:
102
105
  specification_version: 4
103
106
  summary: A collection of helpful methods and monkey patches for Objects, Strings,