rearmed 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/README.md +68 -20
- data/lib/generators/rearmed/setup_generator.rb +11 -4
- data/lib/rearmed/apply_patches.rb +1 -0
- data/lib/rearmed/monkey_patches/array.rb +3 -3
- data/lib/rearmed/monkey_patches/date.rb +1 -1
- data/lib/rearmed/monkey_patches/enumerable.rb +2 -2
- data/lib/rearmed/monkey_patches/hash.rb +13 -2
- data/lib/rearmed/monkey_patches/object.rb +2 -2
- data/lib/rearmed/monkey_patches/rails.rb +109 -5
- data/lib/rearmed/monkey_patches/rails_3.rb +3 -17
- data/lib/rearmed/monkey_patches/rails_4.rb +4 -4
- data/lib/rearmed/monkey_patches/string.rb +15 -4
- data/lib/rearmed/version.rb +1 -1
- data/test/tc_rearmed.rb +201 -17
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2c29c181ff21a0d8d827e5ddc041a24ffdf27e2
|
4
|
+
data.tar.gz: 720e02b98600437a7721e8da557a9cf8a93af7b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce9ee1703ccb3d7cbd44d672e1622760026135fb32fc4e66b59009981cca2d40e31d0b19bfe1623cf1d7b3456934eee62618e2d5c018786e42a5ecd653ce1851
|
7
|
+
data.tar.gz: 4115b29b94fb22028294cdce9996f93ed7428aba08c3f487db6a4ff9c07f24775731d5c4890052ce3aeba824290cca7302ff9e06741ff0bab9c238dd453e7ad2
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,23 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
---------
|
3
3
|
|
4
|
+
- **1.1.0 - July 8, 2016**
|
5
|
+
- Add ActiveRecord `find_or_create`, `reset_table`, `reset_auto_increment`, `depupe`
|
6
|
+
- Add `starts_with?`, `begins_with?`, `ends_with?` aliases
|
7
|
+
- Major improvements to opt-in system
|
8
|
+
- Allow Hash compact work without ActiveSupport
|
9
|
+
- Only allow `in?` patch without ActiveSupport
|
10
|
+
- Move some methods to Rearmed for use outside of monkey patching
|
11
|
+
- Add test's for everything except for the Rails methods (Would love a PR for the Rails tests)
|
12
|
+
- **1.0.3 - June 20, 2016**
|
13
|
+
- Useless version update
|
14
|
+
- I Thought the `delete_first` method still wasn't fixed but my app was incorrect instead
|
15
|
+
- **1.0.2 - June 20, 2016**
|
16
|
+
- Fix array `delete_first` method
|
17
|
+
- **1.0.1 - June 17, 2016**
|
18
|
+
- Add `pluck_to_hash`
|
19
|
+
- Add `pluck_to_struct`
|
20
|
+
- Reorganize rails patches to have generic rails patches
|
4
21
|
- **1.0.0 - June 8, 2016**
|
5
22
|
- Ready for public use
|
6
23
|
- Major improvements to opt-in system
|
data/README.md
CHANGED
@@ -24,7 +24,6 @@ Rearmed.enabled_patches = {
|
|
24
24
|
link_to_confirm: false
|
25
25
|
},
|
26
26
|
rails_3: {
|
27
|
-
hash_compact: false,
|
28
27
|
pluck: false,
|
29
28
|
update_columns: false,
|
30
29
|
all: false
|
@@ -32,17 +31,25 @@ Rearmed.enabled_patches = {
|
|
32
31
|
rails: {
|
33
32
|
pluck_to_hash: false,
|
34
33
|
pluck_to_struct: false,
|
34
|
+
find_or_create: false,
|
35
|
+
reset_table: false,
|
36
|
+
reset_auto_increment: false,
|
37
|
+
dedupe: false,
|
35
38
|
find_relation_each: false,
|
36
39
|
find_in_relation_batches: false,
|
37
40
|
},
|
38
41
|
string: {
|
39
|
-
to_bool: false,
|
40
42
|
valid_integer: false,
|
41
|
-
valid_float: false
|
43
|
+
valid_float: false,
|
44
|
+
to_bool: false,
|
45
|
+
starts_with: false,
|
46
|
+
begins_with: false,
|
47
|
+
ends_with: false
|
42
48
|
},
|
43
49
|
hash: {
|
44
50
|
only: false,
|
45
|
-
dig: false
|
51
|
+
dig: false,
|
52
|
+
compact: false
|
46
53
|
},
|
47
54
|
array: {
|
48
55
|
dig: false,
|
@@ -67,6 +74,8 @@ require 'rearmed/apply_patches'
|
|
67
74
|
### Object
|
68
75
|
```ruby
|
69
76
|
my_var.not_nil?
|
77
|
+
|
78
|
+
# Only for non-Rails environments, as Rails already has this method
|
70
79
|
my_var.in?([1,2,3])
|
71
80
|
my_var.in?(1,2,3) # or with splat arguments
|
72
81
|
```
|
@@ -81,6 +90,11 @@ my_var.in?(1,2,3) # or with splat arguments
|
|
81
90
|
|
82
91
|
'true'.to_bool
|
83
92
|
# or without monkey patch: Rearmed.to_bool('true')
|
93
|
+
|
94
|
+
# alias of start_with? and end_with? to have more sensible method names
|
95
|
+
'foo'.starts_with?('fo') # => true
|
96
|
+
'foo'.begins_with?('fo') # => true
|
97
|
+
'bar'.ends_with?('ar') # => true
|
84
98
|
```
|
85
99
|
|
86
100
|
### Date
|
@@ -92,21 +106,17 @@ Date.now
|
|
92
106
|
```ruby
|
93
107
|
items = ['1.1', '1.11', '1.2']
|
94
108
|
items.natural_sort
|
95
|
-
items.natural_sort(reverse: true) # because natural_sort does not accept a block
|
109
|
+
items.natural_sort(reverse: true) # because natural_sort does not accept a block, accepting PR's on this
|
96
110
|
# or without monkey patch: Rearmed.natural_sort(items) or Rearmed.natural_sort(items, reverse: true)
|
97
111
|
|
98
|
-
items = ['1.1', '1.11', '1.2']
|
99
|
-
items.natural_sort{|a,b| b <=> a}
|
100
|
-
# or without monkey patch: Rearmed.natural_sort(items){|a,b| b <=> a}
|
101
|
-
|
102
112
|
items = [{version: "1.1"}, {version: "1.11"}, {version: "1.2"}]
|
103
113
|
items.natural_sort_by{|x| x[:version]}
|
104
114
|
# or without monkey patch: Rearmed.natural_sort_by(items){|x| x[:version]}
|
105
115
|
|
106
116
|
# Only available on array and hash in Ruby 2.2.x or below
|
107
117
|
items = [{foo: ['foo','bar']}, {test: 'thing'}]
|
108
|
-
items.dig(
|
109
|
-
# or without monkey patch: Rearmed.dig(items
|
118
|
+
items.dig(0, :foo, 1) # => 'bar'
|
119
|
+
# or without monkey patch: Rearmed.dig(items, 0, :foo, 1)
|
110
120
|
```
|
111
121
|
|
112
122
|
### Array Methods
|
@@ -127,33 +137,71 @@ hash.only(:foo, :bar) # => {foo: 'foo'}
|
|
127
137
|
# or without monkey patch: Rearmed.only(hash, :foo, :bar)
|
128
138
|
|
129
139
|
hash.only!(:foo, :bar)
|
140
|
+
|
141
|
+
my_hash.compact
|
142
|
+
my_hash.compact!
|
130
143
|
```
|
131
144
|
|
132
145
|
### Rails
|
133
146
|
|
134
147
|
##### Additional ActiveRecord Methods
|
148
|
+
Note: All methods which involve deletion are compatible with Paranoia & ActsAsParanoid
|
149
|
+
|
135
150
|
```ruby
|
136
|
-
Post.
|
137
|
-
Post.
|
151
|
+
Post.pluck_to_hash(:name, :category, :id)
|
152
|
+
Post.pluck_to_struct(:name, :category, :id)
|
153
|
+
|
154
|
+
Post.find_or_create(name: 'foo', content: 'bar') # use this instead of the super confusing first_or_create method
|
155
|
+
Post.find_or_create!(name: 'foo', content: 'bar')
|
156
|
+
|
157
|
+
Post.reset_table # delete all records from table and reset autoincrement column (id), works with mysql/mariadb/postgresql/sqlite
|
158
|
+
# or with options
|
159
|
+
Post.reset_table(delete_method: :destroy) # to ensure all callbacks are fired
|
160
|
+
|
161
|
+
Post.reset_auto_increment # reset mysql/mariadb/postgresql/sqlite auto-increment column, if contains records then defaults to starting from next available number
|
162
|
+
# or with options
|
163
|
+
Post.reset_auto_increment(value: 1, column: :id) # column option is only relevant for postgresql
|
164
|
+
|
165
|
+
Post.dedupe # remove all duplicate records, defaults to all of the models column_names except timestamps
|
166
|
+
# or with options
|
167
|
+
Post.dedupe(delete_method: :destroy) # to ensure all callbacks are fired
|
168
|
+
Post.dedupe(columns: [:name, :content, :category_id]
|
169
|
+
Post.dedupe(skip_timestamps: false) # skip timestamps defaults to true (created_at, updated_at, deleted_at)
|
170
|
+
Post.dedupe(keep: :last) # Keep the last duplicate instead of the first duplicate by default
|
171
|
+
|
138
172
|
Post.find_in_relation_batches # this returns a relation instead of an array
|
139
173
|
Post.find_relation_each # this returns a relation instead of an array
|
140
174
|
```
|
141
175
|
|
176
|
+
##### Rails 4.x Backports
|
177
|
+
```ruby
|
178
|
+
Post.where(name: 'foo').or.where(content: 'bar')
|
179
|
+
Post.where(name: 'foo').or.my_custom_scope
|
180
|
+
Post.where(name: 'foo').or(Post.where(content: 'bar'))
|
181
|
+
Post.where(name: 'foo).or(content: 'bar')
|
182
|
+
|
183
|
+
= link_to 'Delete', post_path(post), method: :delete, confirm: "Are you sure you want to delete this post?"
|
184
|
+
# returns to rails 3 behaviour of allowing confirm attribute as well as data-confirm
|
185
|
+
```
|
186
|
+
|
142
187
|
##### Rails 3.x Backports
|
143
188
|
```ruby
|
144
|
-
my_hash.compact
|
145
|
-
my_hash.compact!
|
146
189
|
Post.all # Now returns AR relation
|
147
190
|
Post.first.update_columns(a: 'foo', b: 'bar')
|
148
191
|
Post.pluck(:name, :id) # adds multi column pluck support ex. => [['first', 1], ['second', 2], ['third', 3]]
|
192
|
+
|
193
|
+
my_hash.compact # See Hash methods above
|
194
|
+
my_hash.compact!
|
149
195
|
```
|
150
196
|
|
197
|
+
# Contributing / Todo
|
198
|
+
If you want to request a method please raise an issue and we can discuss the implementation.
|
199
|
+
|
200
|
+
If you want to contribute here are a couple of things you could do:
|
201
|
+
|
202
|
+
- Add Tests for Rails methods
|
203
|
+
- Get the `natural_sort` method to accept a block
|
151
204
|
|
152
|
-
##### Rails 4.x Backports
|
153
|
-
```ruby
|
154
|
-
Post.where(name: 'foo').or.where(content: 'bar')
|
155
|
-
= link_to 'Delete', post_path(post), method: :delete, confirm: "Are you sure you want to delete this post?" #returns rails 3 behaviour of allowing confirm attribute as well as data-confirm
|
156
|
-
```
|
157
205
|
|
158
206
|
# Credits
|
159
207
|
Created by Weston Ganger - @westonganger
|
@@ -11,7 +11,6 @@ Rearmed.enabled_patches = {
|
|
11
11
|
link_to_confirm: false
|
12
12
|
},
|
13
13
|
rails_3: {
|
14
|
-
hash_compact: false,
|
15
14
|
pluck: false,
|
16
15
|
update_columns: false,
|
17
16
|
all: false
|
@@ -19,17 +18,25 @@ Rearmed.enabled_patches = {
|
|
19
18
|
rails: {
|
20
19
|
pluck_to_hash: false,
|
21
20
|
pluck_to_struct: false,
|
21
|
+
find_or_create: false,
|
22
|
+
reset_table: false,
|
23
|
+
reset_auto_increment: false,
|
24
|
+
dedupe: false,
|
22
25
|
find_relation_each: false,
|
23
26
|
find_in_relation_batches: false,
|
24
27
|
},
|
25
28
|
string: {
|
26
|
-
to_bool: false,
|
27
29
|
valid_integer: false,
|
28
|
-
valid_float: false
|
30
|
+
valid_float: false,
|
31
|
+
to_bool: false,
|
32
|
+
starts_with: false,
|
33
|
+
begins_with: false,
|
34
|
+
ends_with: false,
|
29
35
|
},
|
30
36
|
hash: {
|
31
37
|
only: false,
|
32
|
-
dig: false
|
38
|
+
dig: false,
|
39
|
+
compact: false,
|
33
40
|
},
|
34
41
|
array: {
|
35
42
|
dig: false,
|
@@ -3,6 +3,7 @@ require 'rearmed/monkey_patches/string'
|
|
3
3
|
require 'rearmed/monkey_patches/array'
|
4
4
|
require 'rearmed/monkey_patches/hash'
|
5
5
|
require 'rearmed/monkey_patches/enumerable'
|
6
|
+
require 'rearmed/monkey_patches/rails'
|
6
7
|
require 'rearmed/monkey_patches/rails_3'
|
7
8
|
require 'rearmed/monkey_patches/rails_4'
|
8
9
|
require 'rearmed/monkey_patches/date'
|
@@ -1,13 +1,13 @@
|
|
1
1
|
array_enabled = Rearmed.enabled_patches[:array] == true
|
2
2
|
|
3
3
|
Array.module_eval do
|
4
|
-
if array_enabled || Rearmed.dig(Rearmed.enabled_patches, :array, :not_empty)
|
4
|
+
if array_enabled || Rearmed.dig(Rearmed.enabled_patches, :array, :not_empty)
|
5
5
|
def not_empty?
|
6
6
|
!empty?
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
if array_enabled || Rearmed.dig(Rearmed.enabled_patches, :array, :delete_first)
|
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
13
|
raise BothArgAndBlockError
|
@@ -21,7 +21,7 @@ Array.module_eval do
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
if RUBY_VERSION.to_f < 2.3 && array_enabled || Rearmed.dig(Rearmed.enabled_patches, :array, :dig)
|
24
|
+
if RUBY_VERSION.to_f < 2.3 && array_enabled || Rearmed.dig(Rearmed.enabled_patches, :array, :dig)
|
25
25
|
def dig(*args)
|
26
26
|
Rearmed.dig(self, *args)
|
27
27
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
date_enabled = Rearmed.enabled_patches[:date] == true
|
2
2
|
|
3
3
|
Date.class_eval do
|
4
|
-
if date_enabled || Rearmed.dig(Rearmed.enabled_patches, :date, :now)
|
4
|
+
if date_enabled || Rearmed.dig(Rearmed.enabled_patches, :date, :now)
|
5
5
|
def self.now
|
6
6
|
DateTime.now.to_date
|
7
7
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
enumerable_enabled = Rearmed.enabled_patches[:enumerable] == true
|
2
2
|
|
3
3
|
Enumerable.module_eval do
|
4
|
-
if enumerable_enabled || Rearmed.dig(Rearmed.enabled_patches, :enumerable, :natural_sort_by)
|
4
|
+
if enumerable_enabled || Rearmed.dig(Rearmed.enabled_patches, :enumerable, :natural_sort_by)
|
5
5
|
def natural_sort_by
|
6
6
|
Rearmed.natural_sort_by(self){|x| yield(x)}
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
if enumerable_enabled || Rearmed.dig(Rearmed.enabled_patches, :enumerable, :natural_sort)
|
10
|
+
if enumerable_enabled || Rearmed.dig(Rearmed.enabled_patches, :enumerable, :natural_sort)
|
11
11
|
def natural_sort(options={})
|
12
12
|
if block_given?
|
13
13
|
Rearmed.natural_sort(self, options){|x| yield(x)}
|
@@ -1,7 +1,18 @@
|
|
1
1
|
hash_enabled = Rearmed.enabled_patches[:hash] == true
|
2
2
|
|
3
3
|
Hash.class_eval do
|
4
|
-
|
4
|
+
allowed = defined?(ActiveSupport) ? (ActiveSupport::VERSION::MAJOR > 3) : true
|
5
|
+
if allowed && (hash_enabled || Rearmed.dig(Rearmed.enabled_patches, :hash, :compact))
|
6
|
+
def compact
|
7
|
+
self.select{|_, value| !value.nil?}
|
8
|
+
end
|
9
|
+
|
10
|
+
def compact!
|
11
|
+
self.reject!{|_, value| value.nil?}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
if hash_enabled || Rearmed.dig(Rearmed.enabled_patches, :hash, :only)
|
5
16
|
def only(*keys)
|
6
17
|
Rearmed.only(self, *keys)
|
7
18
|
end
|
@@ -15,7 +26,7 @@ Hash.class_eval do
|
|
15
26
|
end
|
16
27
|
end
|
17
28
|
|
18
|
-
if RUBY_VERSION.to_f < 2.3 && hash_enabled || Rearmed.dig(Rearmed.enabled_patches, :hash, :dig)
|
29
|
+
if RUBY_VERSION.to_f < 2.3 && hash_enabled || Rearmed.dig(Rearmed.enabled_patches, :hash, :dig)
|
19
30
|
def dig(*args)
|
20
31
|
Rearmed.dig(self, *args)
|
21
32
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
object_enabled = Rearmed.enabled_patches[:object] == true
|
2
2
|
|
3
3
|
Object.class_eval do
|
4
|
-
if object_enabled || Rearmed.dig(Rearmed.enabled_patches, :object, :not_nil)
|
4
|
+
if object_enabled || Rearmed.dig(Rearmed.enabled_patches, :object, :not_nil)
|
5
5
|
def not_nil?
|
6
6
|
!nil?
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
if object_enabled || Rearmed.dig(Rearmed.enabled_patches, :object, :in)
|
10
|
+
if !defined?(ActiveSupport) && (object_enabled || Rearmed.dig(Rearmed.enabled_patches, :object, :in))
|
11
11
|
def in?(array, *more)
|
12
12
|
if !more.empty?
|
13
13
|
array = [array, *more]
|
@@ -2,8 +2,108 @@ enabled = Rearmed.enabled_patches[:rails] == true
|
|
2
2
|
|
3
3
|
if defined?(ActiveRecord)
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
ActiveRecord::Base.class_eval do
|
6
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails, :reset_table)
|
7
|
+
def self.reset_table(opts={})
|
8
|
+
if opts[:delete_method] && opts[:delete_method].to_sym == :destroy
|
9
|
+
if self.try(:paranoid?)
|
10
|
+
self.unscoped.each do |x|
|
11
|
+
if x.respond_to?(:really_destroy!)
|
12
|
+
x.really_destroy!
|
13
|
+
else
|
14
|
+
x.destroy!
|
15
|
+
end
|
16
|
+
end
|
17
|
+
else
|
18
|
+
self.unscoped.destroy_all
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
case self.connection.adapter_name.downcase.to_sym
|
23
|
+
when :mysql2
|
24
|
+
if !opts[:delete_method] || opts[:delete_method].to_sym != :destroy
|
25
|
+
if defined?(ActsAsParanoid) && self.try(:paranoid?)
|
26
|
+
self.unscoped.delete_all!
|
27
|
+
else
|
28
|
+
self.unscoped.delete_all
|
29
|
+
end
|
30
|
+
end
|
31
|
+
self.connection.execute("ALTER TABLE #{self.table_name} AUTO_INCREMENT = 1")
|
32
|
+
when :postgresql
|
33
|
+
self.connection.execute("TRUNCATE TABLE #{self.table_name} RESTART IDENTITY")
|
34
|
+
when :sqlite3
|
35
|
+
self.connection.execute("DELETE FROM #{self.table_name}")
|
36
|
+
self.connection.execute("DELETE FROM sqlite_sequence WHERE NAME='#{self.table_name}'")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails, :reset_auto_increment)
|
42
|
+
def self.reset_auto_increment(opts={})
|
43
|
+
case self.connection.adapter_name.downcase.to_sym
|
44
|
+
when :mysql2
|
45
|
+
opts[:value] = 1 if opts[:value].blank?
|
46
|
+
self.connection.execute("ALTER TABLE #{self.table_name} AUTO_INCREMENT = #{opts[:value]}")
|
47
|
+
when :postgresql
|
48
|
+
opts[:value] = 1 if opts[:value].blank?
|
49
|
+
self.connection.execute("ALTER SEQUENCE #{self.table_name}_#{opts[:column].to_s || 'id'}_seq RESTART WITH #{opts[:value]}")
|
50
|
+
when :sqlite3
|
51
|
+
opts[:value] = 0 if opts[:value].blank?
|
52
|
+
self.connection.execute("UPDATE SQLITE_SEQUENCE SET SEQ=#{opts[:value]} WHERE NAME='#{self.table_name}'")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails, :dedupe)
|
58
|
+
def self.dedupe(opts={})
|
59
|
+
if !opts[:columns]
|
60
|
+
opts[:columns] = self.column_names.reject{|x| x == 'id'}
|
61
|
+
end
|
62
|
+
|
63
|
+
if opts[:skip_timestamps] != false
|
64
|
+
opts[:columns].reject!{|x| ['created_at','updated_at','deleted_at'].include?(x)}
|
65
|
+
end
|
66
|
+
|
67
|
+
self.all.group_by{|model| opts[:columns].map{|x| model[x]}}.values.each do |duplicates|
|
68
|
+
(opts[:keep] && opts[:keep].to_sym == :last) ? duplicates.pop : duplicates.shift
|
69
|
+
if opts[:delete_method] && opts[:delete_method].to_sym == :destroy
|
70
|
+
duplicates.each do |x|
|
71
|
+
if x.respond_to?(:really_destroy!)
|
72
|
+
x.really_destroy!
|
73
|
+
else
|
74
|
+
x.destroy!
|
75
|
+
end
|
76
|
+
end
|
77
|
+
else
|
78
|
+
if defined?(ActsAsParanoid) && self.try(:paranoid?)
|
79
|
+
self.unscoped.where(id: duplicates.collect(&:id)).delete_all!
|
80
|
+
else
|
81
|
+
self.unscoped.where(id: duplicates.collect(&:id)).delete_all
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails, :find_or_create)
|
89
|
+
def self.find_or_create(attrs={}, save_opts={})
|
90
|
+
unless self.where(attrs).limit(1).first
|
91
|
+
x = self.class.new(attrs)
|
92
|
+
x.save(save_opts)
|
93
|
+
return t
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.find_or_create!(attrs={}, save_opts={})
|
98
|
+
unless self.where(attrs).limit(1).first
|
99
|
+
x = self.class.new(attrs)
|
100
|
+
x.save!(save_opts)
|
101
|
+
return t
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails, :pluck_to_hash)
|
7
107
|
def self.pluck_to_hash(*keys)
|
8
108
|
hash_type = keys[-1].is_a?(Hash) ? keys.pop.fetch(:hash_type, HashWithIndifferentAccess) : HashWithIndifferentAccess
|
9
109
|
block_given = block_given?
|
@@ -15,7 +115,9 @@ if defined?(ActiveRecord)
|
|
15
115
|
block_given ? yield(value) : value
|
16
116
|
end
|
17
117
|
end
|
118
|
+
end
|
18
119
|
|
120
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails, :pluck_to_struct)
|
19
121
|
def self.pluck_to_struct(*keys)
|
20
122
|
struct_type = keys[-1].is_a?(Hash) ? keys.pop.fetch(:struct_type, Struct) : Struct
|
21
123
|
block_given = block_given?
|
@@ -28,9 +130,11 @@ if defined?(ActiveRecord)
|
|
28
130
|
block_given ? yield(value) : value
|
29
131
|
end
|
30
132
|
end
|
133
|
+
end
|
31
134
|
|
32
|
-
|
135
|
+
private
|
33
136
|
|
137
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails, :pluck_to_hash) || Rearmed.dig(Rearmed.enabled_patches, :rails, :pluck_to_struct)
|
34
138
|
def self.format_keys(keys)
|
35
139
|
if keys.blank?
|
36
140
|
[column_names, column_names]
|
@@ -52,7 +156,7 @@ if defined?(ActiveRecord)
|
|
52
156
|
end
|
53
157
|
|
54
158
|
ActiveRecord::Batches.module_eval do
|
55
|
-
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails, :find_in_relation_batches)
|
159
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails, :find_in_relation_batches)
|
56
160
|
def find_in_relation_batches(options = {})
|
57
161
|
options.assert_valid_keys(:start, :batch_size)
|
58
162
|
|
@@ -89,7 +193,7 @@ if defined?(ActiveRecord)
|
|
89
193
|
end
|
90
194
|
end
|
91
195
|
|
92
|
-
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails, :find_relation_each)
|
196
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails, :find_relation_each)
|
93
197
|
def find_relation_each(options = {})
|
94
198
|
if block_given?
|
95
199
|
find_in_relation_batches(options) do |records|
|
@@ -1,22 +1,8 @@
|
|
1
1
|
enabled = Rearmed.enabled_patches[:rails_3] == true
|
2
2
|
|
3
|
-
if defined?(ActiveSupport) && ActiveSupport::VERSION::MAJOR < 4
|
4
|
-
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails_3, :hash_compact) == true
|
5
|
-
Hash.class_eval do
|
6
|
-
def compact
|
7
|
-
self.select{|_, value| !value.nil?}
|
8
|
-
end
|
9
|
-
|
10
|
-
def compact!
|
11
|
-
self.reject!{|_, value| value.nil?}
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
3
|
if defined?(ActiveRecord) && ActiveRecord::VERSION::MAJOR < 4
|
18
4
|
|
19
|
-
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails_3, :all)
|
5
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails_3, :all)
|
20
6
|
ActiveRecord::FinderMethods.module_eval do
|
21
7
|
def all(*args)
|
22
8
|
args.any? ? apply_finder_options(args.first) : self
|
@@ -24,7 +10,7 @@ if defined?(ActiveRecord) && ActiveRecord::VERSION::MAJOR < 4
|
|
24
10
|
end
|
25
11
|
end
|
26
12
|
|
27
|
-
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails_3, :update_columns)
|
13
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails_3, :update_columns)
|
28
14
|
ActiveRecord::Persistence::ClassMethods.module_eval do
|
29
15
|
def update_columns(attributes)
|
30
16
|
raise ActiveRecordError, "cannot update a new record" if new_record?
|
@@ -45,7 +31,7 @@ if defined?(ActiveRecord) && ActiveRecord::VERSION::MAJOR < 4
|
|
45
31
|
end
|
46
32
|
end
|
47
33
|
|
48
|
-
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails_3, :pluck)
|
34
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails_3, :pluck)
|
49
35
|
ActiveRecord::Relation.class_eval do
|
50
36
|
def pluck(*args)
|
51
37
|
args.map! do |column_name|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
enabled = Rearmed.enabled_patches[:rails_4] == true
|
2
2
|
|
3
|
-
if defined?(ActionView) && enabled || Rearmed.dig(Rearmed.enabled_patches, :rails_4, :link_to_confirm)
|
3
|
+
if defined?(ActionView) && enabled || Rearmed.dig(Rearmed.enabled_patches, :rails_4, :link_to_confirm)
|
4
4
|
ActionView::Helpers::UrlHelper.module_eval do
|
5
5
|
def convert_options_to_data_attributes(options, html_options)
|
6
6
|
if html_options
|
@@ -25,7 +25,7 @@ end
|
|
25
25
|
if defined?(ActiveRecord)
|
26
26
|
|
27
27
|
ActiveRecord::Batches.module_eval do
|
28
|
-
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails_4, :find_in_relation_batches)
|
28
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails_4, :find_in_relation_batches)
|
29
29
|
def find_in_relation_batches(options = {})
|
30
30
|
options.assert_valid_keys(:start, :batch_size)
|
31
31
|
|
@@ -62,7 +62,7 @@ if defined?(ActiveRecord)
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails_4, :find_relation_each)
|
65
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails_4, :find_relation_each)
|
66
66
|
def find_relation_each(options = {})
|
67
67
|
if block_given?
|
68
68
|
find_in_relation_batches(options) do |records|
|
@@ -78,7 +78,7 @@ if defined?(ActiveRecord)
|
|
78
78
|
end
|
79
79
|
|
80
80
|
|
81
|
-
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails_4, :or)
|
81
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails_4, :or)
|
82
82
|
module ActiveRecord
|
83
83
|
module Querying
|
84
84
|
delegate :or, :to => :all
|
@@ -1,22 +1,33 @@
|
|
1
1
|
string_enabled = Rearmed.enabled_patches[:string] == true
|
2
2
|
|
3
3
|
String.class_eval do
|
4
|
-
if string_enabled || Rearmed.dig(Rearmed.enabled_patches, :string, :valid_integer)
|
4
|
+
if string_enabled || Rearmed.dig(Rearmed.enabled_patches, :string, :valid_integer)
|
5
5
|
def valid_integer?
|
6
6
|
Rearmed.valid_integer?(self)
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
if string_enabled || Rearmed.dig(Rearmed.enabled_patches, :string, :valid_float)
|
10
|
+
if string_enabled || Rearmed.dig(Rearmed.enabled_patches, :string, :valid_float)
|
11
11
|
def valid_float?
|
12
12
|
Rearmed.valid_float?(self)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
if string_enabled || Rearmed.dig(Rearmed.enabled_patches, :string, :to_bool)
|
16
|
+
if string_enabled || Rearmed.dig(Rearmed.enabled_patches, :string, :to_bool)
|
17
17
|
def to_bool
|
18
18
|
Rearmed.to_bool(self)
|
19
19
|
end
|
20
20
|
end
|
21
|
-
end
|
22
21
|
|
22
|
+
if string_enabled || Rearmed.dig(Rearmed.enabled_patches, :string, :starts_with)
|
23
|
+
alias_method :starts_with?, :start_with?
|
24
|
+
end
|
25
|
+
|
26
|
+
if string_enabled || Rearmed.dig(Rearmed.enabled_patches, :string, :begins_with)
|
27
|
+
alias_method :begins_with?, :start_with?
|
28
|
+
end
|
29
|
+
|
30
|
+
if string_enabled || Rearmed.dig(Rearmed.enabled_patches, :string, :ends_with)
|
31
|
+
alias_method :ends_with?, :end_with?
|
32
|
+
end
|
33
|
+
end
|
data/lib/rearmed/version.rb
CHANGED
data/test/tc_rearmed.rb
CHANGED
@@ -1,33 +1,217 @@
|
|
1
1
|
#!/usr/bin/env ruby -w
|
2
|
-
require 'yaml'
|
3
|
-
require 'minitest'
|
4
2
|
|
5
3
|
lib = File.expand_path('../lib', __FILE__)
|
6
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
7
|
-
|
5
|
+
|
6
|
+
require 'yaml'
|
7
|
+
require 'minitest'
|
8
|
+
|
9
|
+
require 'rearmed'
|
8
10
|
|
9
11
|
require 'minitest/autorun'
|
10
12
|
|
11
13
|
class TestRearmed < MiniTest::Test
|
12
14
|
def setup
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
Minitest::Assertions.module_eval do
|
16
|
+
alias_method :eql, :assert_equal
|
17
|
+
end
|
18
|
+
|
19
|
+
Rearmed.enabled_patches = {
|
20
|
+
array: true,
|
21
|
+
hash: true,
|
22
|
+
object: true,
|
23
|
+
string: true,
|
24
|
+
date: true,
|
25
|
+
enumerable: true,
|
26
|
+
rails_3: true,
|
27
|
+
rails_4: true,
|
28
|
+
rails: true
|
29
|
+
}
|
30
|
+
require 'rearmed/apply_patches'
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_string
|
34
|
+
# Test String Methods
|
35
|
+
str = '32'
|
36
|
+
eql(str.valid_integer?, true)
|
37
|
+
|
38
|
+
str = '32.2'
|
39
|
+
eql(str.valid_integer?, false)
|
40
|
+
|
41
|
+
str = '32a'
|
42
|
+
eql(str.valid_integer?, false)
|
43
|
+
|
44
|
+
str = '132.2'
|
45
|
+
eql(str.valid_float?, true)
|
46
|
+
|
47
|
+
str = '132.2.2'
|
48
|
+
eql(str.valid_float?, false)
|
49
|
+
|
50
|
+
str = '12.1a'
|
51
|
+
eql(str.valid_float?, false)
|
52
|
+
|
53
|
+
str = 'true'
|
54
|
+
eql(str.to_bool, true)
|
55
|
+
|
56
|
+
str = 'false'
|
57
|
+
eql(str.to_bool, false)
|
58
|
+
|
59
|
+
str = 'not true'
|
60
|
+
eql(str.to_bool, nil)
|
61
|
+
|
62
|
+
|
63
|
+
# Test Rearmed methods (just cause really)
|
64
|
+
str = 'true'
|
65
|
+
eql(Rearmed.to_bool(str), true)
|
66
|
+
|
67
|
+
str = '12'
|
68
|
+
eql(Rearmed.valid_integer?(str), true)
|
69
|
+
|
70
|
+
str = '1.2'
|
71
|
+
eql(Rearmed.valid_float?(str), true)
|
16
72
|
end
|
17
73
|
|
18
|
-
def
|
19
|
-
|
74
|
+
def test_date
|
75
|
+
Date.now
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_enumerable
|
79
|
+
items = ['1.1', '1.11', '1.2']
|
80
|
+
|
81
|
+
eql(items.natural_sort, ['1.1','1.2','1.11'])
|
82
|
+
|
83
|
+
eql(items.natural_sort(reverse: true), ['1.11','1.2','1.1'])
|
84
|
+
|
85
|
+
eql(Rearmed.natural_sort(items), ['1.1','1.2','1.11'])
|
86
|
+
|
87
|
+
eql(Rearmed.natural_sort(items, reverse: true), ['1.11','1.2','1.1'])
|
88
|
+
|
89
|
+
|
90
|
+
items = [{version: "1.1"}, {version: "1.11"}, {version: "1.2"}]
|
20
91
|
|
21
|
-
|
22
|
-
assert_equal "1.22", @array.natural_sort{|a,b| b <=> a}[0]
|
23
|
-
assert_equal "1.2", @array.natural_sort_by{|x| x}[1]
|
92
|
+
eql(items.natural_sort_by{|x| x[:version]}, [{version: "1.1"}, {version: "1.2"}, {version: "1.11"}])
|
24
93
|
|
25
|
-
|
26
|
-
|
27
|
-
|
94
|
+
eql(Rearmed.natural_sort_by(items){|x| x[:version]}, [{version: "1.1"}, {version: "1.2"}, {version: "1.11"}])
|
95
|
+
|
96
|
+
|
97
|
+
# Only available on array and hash in Ruby 2.2.x or below
|
98
|
+
array = [{foo: ['foo','bar']}, {test: 'thing'}]
|
99
|
+
|
100
|
+
eql(array.dig(0, :foo, 1), 'bar')
|
101
|
+
eql(array.dig(0, :foo, 2), nil)
|
102
|
+
|
103
|
+
eql(Rearmed.dig(array, 1, :test), 'thing')
|
104
|
+
eql(Rearmed.dig(array, 1, :bar), nil)
|
105
|
+
|
106
|
+
hash = {a: {foo: ['bar']}, b: {c: 'c'}}
|
107
|
+
|
108
|
+
eql(hash.dig(:a, :foo, 0), 'bar')
|
109
|
+
eql(Rearmed.dig(hash, :b, :c), 'c')
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_array
|
113
|
+
array = [1,3,2,1,3,4,1]
|
114
|
+
array.delete_first(3)
|
115
|
+
eql(array, [1,2,1,3,4,1])
|
116
|
+
|
117
|
+
array = [1,3,2,1,3,4,1]
|
118
|
+
array.delete_first
|
119
|
+
eql(array, [3,2,1,3,4,1])
|
120
|
+
|
121
|
+
array = [1,3,2,1,3,4,1]
|
122
|
+
array.delete_first{|x| x != 1}
|
123
|
+
eql(array, [1,2,1,3,4,1])
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_hash
|
127
|
+
hash = {foo: 'foo', bar: 'bar', other: 'other'}
|
128
|
+
eql(hash.only(:foo, :bar), {foo: 'foo', bar: 'bar'})
|
129
|
+
|
130
|
+
hash = {foo: 'foo', bar: 'bar', other: 'other'}
|
131
|
+
hash.only!(:foo, :bar)
|
132
|
+
eql(hash, {foo: 'foo', bar: 'bar'})
|
133
|
+
|
134
|
+
hash = {foo: 'foo', bar: 'bar', other: 'other'}
|
135
|
+
eql(Rearmed.only(hash, :foo, :bar), {foo: 'foo', bar: 'bar'})
|
136
|
+
|
137
|
+
|
138
|
+
hash = {foo: nil, bar: nil, other: 'other'}
|
139
|
+
eql(hash.compact, {other: 'other'})
|
140
|
+
|
141
|
+
hash = {foo: nil, bar: nil, other: 'other'}
|
142
|
+
hash.compact!
|
143
|
+
eql(hash, {other: 'other'})
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_object
|
147
|
+
str = 'test'
|
148
|
+
eql(str.not_nil?, true)
|
149
|
+
|
150
|
+
str = nil
|
151
|
+
eql(str.not_nil?, false)
|
152
|
+
|
153
|
+
str = false
|
154
|
+
eql(str.not_nil?, true)
|
155
|
+
|
156
|
+
str = 'test'
|
157
|
+
eql(str.in?(['test','abc']), true)
|
158
|
+
|
159
|
+
str = 'test'
|
160
|
+
eql(str.in?(['abc','def']), false)
|
161
|
+
|
162
|
+
str = 'test'
|
163
|
+
eql(str.in?('test','abc'), true)
|
164
|
+
|
165
|
+
str = 'test'
|
166
|
+
eql(str.in?('abc','def'), false)
|
167
|
+
|
168
|
+
str = 'test'
|
169
|
+
eql(str.in?('a test string'), true)
|
170
|
+
|
171
|
+
str = 'test'
|
172
|
+
eql(str.in?('a real string'), false)
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_general_rails
|
176
|
+
# THE MOST IMPORTANT TESTS HERE WOULD BE dedupe, reset_auto_increment, reset_table
|
177
|
+
|
178
|
+
#Post.reset_table # delete all records from table and reset autoincrement column (id), works with mysql/mariadb/postgresql/sqlite
|
179
|
+
# or with options
|
180
|
+
#Post.reset_table(delete_method: :destroy) # use destroy_all to ensure all callbacks are fired
|
181
|
+
|
182
|
+
#Post.reset_auto_increment # reset mysql/mariadb/postgresql/sqlite auto-increment column
|
183
|
+
# or with options
|
184
|
+
#Post.reset_auto_increment(value: 1, column: :id)
|
185
|
+
|
186
|
+
#Post.dedupe # remove all duplicate records, defaults to the models column_names list
|
187
|
+
# or with options
|
188
|
+
#Post.dedupe(columns: [:name, :content, :category_id])
|
189
|
+
#Post.dedupe(skip_timestamps: true)
|
190
|
+
#Post.pluck_to_hash(:name, :category, :id)
|
191
|
+
#Post.pluck_to_struct(:name, :category, :id)
|
192
|
+
|
193
|
+
#Post.find_or_create(name: 'foo', content: 'bar') # use this instead of the super confusing first_or_create method
|
194
|
+
#Post.find_or_create!(name: 'foo', content: 'bar')
|
195
|
+
|
196
|
+
#Post.find_in_relation_batches # this returns a relation instead of an array
|
197
|
+
#Post.find_relation_each # this returns a relation instead of an array
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_rails_3
|
201
|
+
#my_hash.compact
|
202
|
+
#my_hash.compact!
|
203
|
+
#Post.all # Now returns AR relation
|
204
|
+
#Post.first.update_columns(a: 'foo', b: 'bar')
|
205
|
+
#Post.pluck(:name, :id) # adds multi column pluck support ex. => [['first', 1], ['second', 2], ['third', 3]]
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_rails_4
|
209
|
+
#Post.where(name: 'foo').or.where(content: 'bar')
|
210
|
+
#Post.where(name: 'foo').or.my_custom_scope
|
211
|
+
#Post.where(name: 'foo').or(Post.where(content: 'bar'))
|
212
|
+
#Post.where(name: 'foo).or(content: 'bar')
|
28
213
|
|
29
|
-
|
30
|
-
#
|
31
|
-
#assert_equal({version: "1.2"}, @hash_array.natural_sort_by{|x| x[:version]}[1])
|
214
|
+
#= link_to 'Delete', post_path(post), method: :delete, confirm: "Are you sure you want to delete this post?"
|
215
|
+
# returns to rails 3 behaviour of allowing confirm attribute as well as data-confirm
|
32
216
|
end
|
33
217
|
end
|
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.0
|
4
|
+
version: 1.1.0
|
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-
|
11
|
+
date: 2016-07-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|