rearmed 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +36 -9
- data/lib/generators/rearmed/setup_generator.rb +6 -1
- data/lib/rearmed.rb +24 -8
- data/lib/rearmed/apply_patches.rb +1 -0
- data/lib/rearmed/monkey_patches/minitest.rb +35 -0
- data/lib/rearmed/monkey_patches/rails.rb +58 -18
- data/lib/rearmed/version.rb +1 -1
- data/test/tc_rearmed.rb +47 -13
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 270b7582528a427dfcd54ea2cbe616af8bc67717
|
4
|
+
data.tar.gz: e97b0352883c108aa366ec3078bf188349e1b907
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4785d8f2332220c02dbe2d904ef328ff4554b98f6711c5e095a071beb52c6000ae540228c53f732beb9987e435c7d8c5820fb317d959fa4815b2f6e8247cf00
|
7
|
+
data.tar.gz: 9f77a7b3b1e35f8027b00d676076e7e90ce33b88e34efdaa82b927c57b1caaa5e69bb8aa108b8b29c9f220911c45879d29f0dfa6d6df29d6d151cca0efec22dc
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
---------
|
3
3
|
|
4
|
+
-
|
5
|
+
- **1.2.0 - September 3, 2016**
|
6
|
+
- Add Minitest patches `assert_changed` & `assert_not_changed`
|
7
|
+
- Remove `dedupe` in favor of new `find_duplicates`
|
8
|
+
- Add ActiveRecord `newest`
|
9
|
+
- **1.1.1 - August 20, 2016**
|
10
|
+
- Add Array `not_empty?`
|
4
11
|
- **1.1.0 - July 8, 2016**
|
5
12
|
- Add ActiveRecord `find_or_create`, `reset_table`, `reset_auto_increment`, `depupe`
|
6
13
|
- Add `starts_with?`, `begins_with?`, `ends_with?` aliases
|
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, & Rails
|
4
|
+
A collection of helpful methods and monkey patches for Objects, Strings, Enumerables, Arrays, Hash, Dates, Minitest & Rails
|
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
|
|
@@ -32,9 +32,10 @@ Rearmed.enabled_patches = {
|
|
32
32
|
pluck_to_hash: false,
|
33
33
|
pluck_to_struct: false,
|
34
34
|
find_or_create: false,
|
35
|
+
find_duplicates: false,
|
36
|
+
newest: false,
|
35
37
|
reset_table: false,
|
36
38
|
reset_auto_increment: false,
|
37
|
-
dedupe: false,
|
38
39
|
find_relation_each: false,
|
39
40
|
find_in_relation_batches: false,
|
40
41
|
},
|
@@ -66,6 +67,10 @@ Rearmed.enabled_patches = {
|
|
66
67
|
},
|
67
68
|
date: {
|
68
69
|
now: false
|
70
|
+
},
|
71
|
+
minitest: {
|
72
|
+
assert_changed: false,
|
73
|
+
assert_not_changed: false
|
69
74
|
}
|
70
75
|
}
|
71
76
|
|
@@ -157,6 +162,19 @@ Post.pluck_to_struct(:name, :category, :id)
|
|
157
162
|
Post.find_or_create(name: 'foo', content: 'bar') # use this instead of the super confusing first_or_create method
|
158
163
|
Post.find_or_create!(name: 'foo', content: 'bar')
|
159
164
|
|
165
|
+
Post.find_duplicates # return active record relation of all records that have duplicates. By default it skips the primary_key, created_at, updated_at, & deleted_at columns
|
166
|
+
Post.find_duplicates(:name) # find duplicates based on the name attribute
|
167
|
+
Post.find_duplicates(:name, :category) # find duplicates based on the name & category attribute
|
168
|
+
Post.find_duplicates(self.column_names.reject{|x| ['id','created_at','updated_at','deleted_at'].include?(x)})
|
169
|
+
|
170
|
+
# It also can delete duplicates. Valid values for keep are :first & :last. Valid values for delete_method are :destroy & :delete. soft_delete is only used if you are using acts_as_paranoid on your model.
|
171
|
+
Post.find_duplicates(:name, :category, delete: true)
|
172
|
+
Post.find_duplicates(:name, :category, delete: {keep: :first, delete_method: :destroy, soft_delete: true}) # these are the default settings for delete: true
|
173
|
+
|
174
|
+
Post.newest # get the newest post, by default ordered by :created_at
|
175
|
+
Post.newest(:updated_at) # different sort order
|
176
|
+
Post.newest(:published_at, :created_at) # multiple columns to sort on
|
177
|
+
|
160
178
|
Post.reset_table # delete all records from table and reset autoincrement column (id), works with mysql/mariadb/postgresql/sqlite
|
161
179
|
# or with options
|
162
180
|
Post.reset_table(delete_method: :destroy) # to ensure all callbacks are fired
|
@@ -165,13 +183,6 @@ Post.reset_auto_increment # reset mysql/mariadb/postgresql/sqlite auto-increment
|
|
165
183
|
# or with options
|
166
184
|
Post.reset_auto_increment(value: 1, column: :id) # column option is only relevant for postgresql
|
167
185
|
|
168
|
-
Post.dedupe # remove all duplicate records, defaults to all of the models column_names except timestamps
|
169
|
-
# or with options
|
170
|
-
Post.dedupe(delete_method: :destroy) # to ensure all callbacks are fired
|
171
|
-
Post.dedupe(columns: [:name, :content, :category_id]
|
172
|
-
Post.dedupe(skip_timestamps: false) # skip timestamps defaults to true (created_at, updated_at, deleted_at)
|
173
|
-
Post.dedupe(keep: :last) # Keep the last duplicate instead of the first duplicate by default
|
174
|
-
|
175
186
|
Post.find_in_relation_batches # this returns a relation instead of an array
|
176
187
|
Post.find_relation_each # this returns a relation instead of an array
|
177
188
|
```
|
@@ -197,6 +208,21 @@ my_hash.compact # See Hash methods above
|
|
197
208
|
my_hash.compact!
|
198
209
|
```
|
199
210
|
|
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
|
+
|
200
226
|
# Contributing / Todo
|
201
227
|
If you want to request a method please raise an issue and we can discuss the implementation.
|
202
228
|
|
@@ -204,6 +230,7 @@ If you want to contribute here are a couple of things you could do:
|
|
204
230
|
|
205
231
|
- Add Tests for Rails methods
|
206
232
|
- 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 ``
|
207
234
|
|
208
235
|
|
209
236
|
# Credits
|
@@ -19,9 +19,10 @@ Rearmed.enabled_patches = {
|
|
19
19
|
pluck_to_hash: false,
|
20
20
|
pluck_to_struct: false,
|
21
21
|
find_or_create: false,
|
22
|
+
find_duplicates: false,
|
23
|
+
newest: false,
|
22
24
|
reset_table: false,
|
23
25
|
reset_auto_increment: false,
|
24
|
-
dedupe: false,
|
25
26
|
find_relation_each: false,
|
26
27
|
find_in_relation_batches: false,
|
27
28
|
},
|
@@ -53,6 +54,10 @@ Rearmed.enabled_patches = {
|
|
53
54
|
},
|
54
55
|
date: {
|
55
56
|
now: false
|
57
|
+
},
|
58
|
+
minitest: {
|
59
|
+
assert_changed: false,
|
60
|
+
assert_not_changed: false
|
56
61
|
}
|
57
62
|
}
|
58
63
|
|
data/lib/rearmed.rb
CHANGED
@@ -3,28 +3,40 @@ module Rearmed
|
|
3
3
|
@enabled_patches = {
|
4
4
|
rails_4: {
|
5
5
|
or: false,
|
6
|
-
link_to_confirm: false
|
7
|
-
find_relation_each: false,
|
8
|
-
find_in_relation_batches: false
|
6
|
+
link_to_confirm: false
|
9
7
|
},
|
10
8
|
rails_3: {
|
11
|
-
hash_compact: false,
|
12
9
|
pluck: false,
|
13
10
|
update_columns: false,
|
14
11
|
all: false
|
15
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
|
+
},
|
16
23
|
string: {
|
17
|
-
to_bool: false,
|
18
24
|
valid_integer: false,
|
19
|
-
valid_float: false
|
25
|
+
valid_float: false,
|
26
|
+
to_bool: false,
|
27
|
+
starts_with: false,
|
28
|
+
begins_with: false,
|
29
|
+
ends_with: false
|
20
30
|
},
|
21
31
|
hash: {
|
22
32
|
only: false,
|
23
|
-
dig: false
|
33
|
+
dig: false,
|
34
|
+
compact: false
|
24
35
|
},
|
25
36
|
array: {
|
26
37
|
dig: false,
|
27
|
-
delete_first: false
|
38
|
+
delete_first: false,
|
39
|
+
not_empty: false
|
28
40
|
},
|
29
41
|
enumerable: {
|
30
42
|
natural_sort: false,
|
@@ -36,6 +48,10 @@ module Rearmed
|
|
36
48
|
},
|
37
49
|
date: {
|
38
50
|
now: false
|
51
|
+
},
|
52
|
+
minitest: {
|
53
|
+
assert_changed: false,
|
54
|
+
assert_not_changed: false
|
39
55
|
}
|
40
56
|
}
|
41
57
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
if defined?(Minitest::Assertions)
|
2
|
+
|
3
|
+
enabled = Rearmed.enabled_patches[:minitest] == true
|
4
|
+
|
5
|
+
Minitest::Assertions.module_eval do
|
6
|
+
|
7
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :minitest, :assert_changed)
|
8
|
+
def assert_changed(expression, &block)
|
9
|
+
if expression.respond_to?(:call)
|
10
|
+
e = expression
|
11
|
+
else
|
12
|
+
e = lambda{ block.binding.eval(expression) }
|
13
|
+
end
|
14
|
+
old = e.call
|
15
|
+
block.call
|
16
|
+
refute_equal old, e.call
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :minitest, :assert_not_changed)
|
21
|
+
def assert_not_changed(expression, &block)
|
22
|
+
if expression.respond_to?(:call)
|
23
|
+
e = expression
|
24
|
+
else
|
25
|
+
e = lambda{ block.binding.eval(expression) }
|
26
|
+
end
|
27
|
+
old = e.call
|
28
|
+
block.call
|
29
|
+
assert_equal old, e.call
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -3,6 +3,20 @@ enabled = Rearmed.enabled_patches[:rails] == true
|
|
3
3
|
if defined?(ActiveRecord)
|
4
4
|
|
5
5
|
ActiveRecord::Base.class_eval do
|
6
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails, :newest)
|
7
|
+
def self.newest(*columns)
|
8
|
+
if columns.empty? || !columns.to_s.include?('created_at')
|
9
|
+
columns << 'created_at'
|
10
|
+
end
|
11
|
+
|
12
|
+
the_order = {}
|
13
|
+
columns.each do |x|
|
14
|
+
the_order[x.to_s] = :desc
|
15
|
+
end
|
16
|
+
self.order(the_order).limit(1).first
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
6
20
|
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails, :reset_table)
|
7
21
|
def self.reset_table(opts={})
|
8
22
|
if opts[:delete_method] && opts[:delete_method].to_sym == :destroy
|
@@ -46,7 +60,7 @@ if defined?(ActiveRecord)
|
|
46
60
|
self.connection.execute("ALTER TABLE #{self.table_name} AUTO_INCREMENT = #{opts[:value]}")
|
47
61
|
when :postgresql
|
48
62
|
opts[:value] = 1 if opts[:value].blank?
|
49
|
-
self.connection.execute("ALTER SEQUENCE #{self.table_name}_#{opts[:column].to_s ||
|
63
|
+
self.connection.execute("ALTER SEQUENCE #{self.table_name}_#{opts[:column].to_s || self.primary_key}_seq RESTART WITH #{opts[:value]}")
|
50
64
|
when :sqlite3
|
51
65
|
opts[:value] = 0 if opts[:value].blank?
|
52
66
|
self.connection.execute("UPDATE SQLITE_SEQUENCE SET SEQ=#{opts[:value]} WHERE NAME='#{self.table_name}'")
|
@@ -54,33 +68,59 @@ if defined?(ActiveRecord)
|
|
54
68
|
end
|
55
69
|
end
|
56
70
|
|
57
|
-
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails, :
|
58
|
-
def self.
|
59
|
-
|
60
|
-
|
71
|
+
if enabled || Rearmed.dig(Rearmed.enabled_patches, :rails, :find_duplicates)
|
72
|
+
def self.find_duplicates(*args)
|
73
|
+
options = {}
|
74
|
+
|
75
|
+
unless args.empty?
|
76
|
+
if args.last.is_a?(Hash)
|
77
|
+
options = args.pop
|
78
|
+
end
|
79
|
+
|
80
|
+
unless args.empty?
|
81
|
+
if args.count == 1 && args.first.is_a?(Array)
|
82
|
+
args = args.first
|
83
|
+
end
|
84
|
+
|
85
|
+
options[:columns] = args
|
86
|
+
end
|
61
87
|
end
|
62
88
|
|
63
|
-
|
64
|
-
|
65
|
-
|
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)
|
66
92
|
|
67
|
-
|
68
|
-
|
69
|
-
|
93
|
+
if options[:delete]
|
94
|
+
if options[:delete] == true
|
95
|
+
options[:delete] = {keep: :first, delete_method: :destroy, soft_delete: true}
|
96
|
+
else
|
97
|
+
options[:delete][:delete_method] ||= :destroy
|
98
|
+
options[:delete][:keep] ||= :first
|
99
|
+
if options[:delete][:soft_delete] != false
|
100
|
+
options[:delete][:soft_delete] = true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
duplicates = self.where.not(self.primary_key => ids)
|
105
|
+
|
106
|
+
if options[:delete][:delete_method].to_sym == :delete
|
107
|
+
if x.respond_to?(:delete_all!)
|
108
|
+
duplicates.delete_all!
|
109
|
+
else
|
110
|
+
duplicates.delete_all
|
111
|
+
end
|
112
|
+
else
|
70
113
|
duplicates.each do |x|
|
71
|
-
if x.respond_to?(:really_destroy!)
|
114
|
+
if !options[:delete][:soft_delete] && x.respond_to?(:really_destroy!)
|
72
115
|
x.really_destroy!
|
73
116
|
else
|
74
117
|
x.destroy!
|
75
118
|
end
|
76
119
|
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
120
|
end
|
121
|
+
return nil
|
122
|
+
else
|
123
|
+
return self.where.not(self.primary_key => ids)
|
84
124
|
end
|
85
125
|
end
|
86
126
|
end
|
data/lib/rearmed/version.rb
CHANGED
data/test/tc_rearmed.rb
CHANGED
@@ -25,7 +25,8 @@ class TestRearmed < MiniTest::Test
|
|
25
25
|
enumerable: true,
|
26
26
|
rails_3: true,
|
27
27
|
rails_4: true,
|
28
|
-
rails: true
|
28
|
+
rails: true,
|
29
|
+
minitest: true
|
29
30
|
}
|
30
31
|
require 'rearmed/apply_patches'
|
31
32
|
end
|
@@ -174,27 +175,60 @@ class TestRearmed < MiniTest::Test
|
|
174
175
|
eql(str.in?('a real string'), false)
|
175
176
|
end
|
176
177
|
|
178
|
+
def test_minitest
|
179
|
+
str = 'first'
|
180
|
+
assert_changed "str" do
|
181
|
+
str = 'second'
|
182
|
+
end
|
183
|
+
|
184
|
+
str = 'first'
|
185
|
+
assert_changed ->{ str } do
|
186
|
+
str = 'second'
|
187
|
+
end
|
188
|
+
|
189
|
+
name = 'first'
|
190
|
+
assert_changed lambda{ name } do
|
191
|
+
name = 'second'
|
192
|
+
end
|
193
|
+
|
194
|
+
name = 'first'
|
195
|
+
assert_not_changed 'name' do
|
196
|
+
name = 'first'
|
197
|
+
end
|
198
|
+
|
199
|
+
name = 'first'
|
200
|
+
assert_not_changed ->{ name } do
|
201
|
+
name = 'first'
|
202
|
+
end
|
203
|
+
|
204
|
+
name = 'first'
|
205
|
+
assert_not_changed lambda{ name } do
|
206
|
+
name = 'first'
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
177
210
|
def test_general_rails
|
178
211
|
# THE MOST IMPORTANT TESTS HERE WOULD BE dedupe, reset_auto_increment, reset_table
|
179
212
|
|
180
|
-
#Post.reset_table # delete all records from table and reset autoincrement column (id), works with mysql/mariadb/postgresql/sqlite
|
181
|
-
# or with options
|
182
|
-
#Post.reset_table(delete_method: :destroy) # use destroy_all to ensure all callbacks are fired
|
183
|
-
|
184
|
-
#Post.reset_auto_increment # reset mysql/mariadb/postgresql/sqlite auto-increment column
|
185
|
-
# or with options
|
186
|
-
#Post.reset_auto_increment(value: 1, column: :id)
|
187
|
-
|
188
|
-
#Post.dedupe # remove all duplicate records, defaults to the models column_names list
|
189
|
-
# or with options
|
190
|
-
#Post.dedupe(columns: [:name, :content, :category_id])
|
191
|
-
#Post.dedupe(skip_timestamps: true)
|
192
213
|
#Post.pluck_to_hash(:name, :category, :id)
|
193
214
|
#Post.pluck_to_struct(:name, :category, :id)
|
194
215
|
|
195
216
|
#Post.find_or_create(name: 'foo', content: 'bar') # use this instead of the super confusing first_or_create method
|
196
217
|
#Post.find_or_create!(name: 'foo', content: 'bar')
|
197
218
|
|
219
|
+
#Post.find_duplicates # return active record relation of all records that have duplicates
|
220
|
+
#Post.find_duplicates(:name) # find duplicates based on the name attribute
|
221
|
+
#Post.find_duplicates([:name, :category]) # find duplicates based on the name & category attribute
|
222
|
+
#Post.find_duplicates(name: 'A Specific Name')
|
223
|
+
|
224
|
+
#Post.reset_table # delete all records from table and reset autoincrement column (id), works with mysql/mariadb/postgresql/sqlite
|
225
|
+
## or with options
|
226
|
+
#Post.reset_table(delete_method: :destroy) # to ensure all callbacks are fired
|
227
|
+
|
228
|
+
#Post.reset_auto_increment # reset mysql/mariadb/postgresql/sqlite auto-increment column, if contains records then defaults to starting from next available number
|
229
|
+
## or with options
|
230
|
+
#Post.reset_auto_increment(value: 1, column: :id) # column option is only relevant for postgresql
|
231
|
+
|
198
232
|
#Post.find_in_relation_batches # this returns a relation instead of an array
|
199
233
|
#Post.find_relation_each # this returns a relation instead of an array
|
200
234
|
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.
|
4
|
+
version: 1.2.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-09-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
description: A collection of helpful methods and monkey patches for Objects, Strings,
|
56
|
-
Enumerables, Arrays, Hash, Dates, & Rails
|
56
|
+
Enumerables, Arrays, Hash, Dates, Minitest & Rails
|
57
57
|
email: westonganger@gmail.com
|
58
58
|
executables: []
|
59
59
|
extensions: []
|
@@ -70,6 +70,7 @@ files:
|
|
70
70
|
- lib/rearmed/monkey_patches/date.rb
|
71
71
|
- lib/rearmed/monkey_patches/enumerable.rb
|
72
72
|
- lib/rearmed/monkey_patches/hash.rb
|
73
|
+
- lib/rearmed/monkey_patches/minitest.rb
|
73
74
|
- lib/rearmed/monkey_patches/object.rb
|
74
75
|
- lib/rearmed/monkey_patches/rails.rb
|
75
76
|
- lib/rearmed/monkey_patches/rails_3.rb
|
@@ -100,6 +101,6 @@ rubygems_version: 2.5.1
|
|
100
101
|
signing_key:
|
101
102
|
specification_version: 4
|
102
103
|
summary: A collection of helpful methods and monkey patches for Objects, Strings,
|
103
|
-
Enumerables, Arrays, Hash, Dates, & Rails
|
104
|
+
Enumerables, Arrays, Hash, Dates, Minitest & Rails
|
104
105
|
test_files:
|
105
106
|
- test/tc_rearmed.rb
|