dm_ruby_extensions 1.0.9 → 1.6.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 +5 -5
- data/CHANGELOG.md +19 -0
- data/README.md +133 -79
- data/lib/dm_ruby_extensions/extend_array.rb +8 -6
- data/lib/dm_ruby_extensions/extend_date.rb +7 -8
- data/lib/dm_ruby_extensions/extend_datetime.rb +6 -7
- data/lib/dm_ruby_extensions/extend_false.rb +2 -3
- data/lib/dm_ruby_extensions/extend_hash.rb +36 -30
- data/lib/dm_ruby_extensions/extend_integer.rb +5 -4
- data/lib/dm_ruby_extensions/extend_nil.rb +11 -11
- data/lib/dm_ruby_extensions/extend_numeric.rb +4 -2
- data/lib/dm_ruby_extensions/extend_string.rb +56 -52
- data/lib/dm_ruby_extensions/extend_time.rb +4 -5
- data/lib/dm_ruby_extensions/extend_true.rb +2 -3
- data/lib/dm_ruby_extensions/version.rb +3 -1
- data/lib/dm_ruby_extensions.rb +15 -12
- metadata +19 -42
- data/.gitignore +0 -20
- data/.rspec +0 -3
- data/.travis.yml +0 -7
- data/Gemfile +0 -7
- data/Rakefile +0 -7
- data/dm_ruby_extensions.gemspec +0 -21
- data/spec/extensions/array_spec.rb +0 -39
- data/spec/extensions/date_spec.rb +0 -29
- data/spec/extensions/datetime_spec.rb +0 -29
- data/spec/extensions/false_spec.rb +0 -11
- data/spec/extensions/hash_spec.rb +0 -55
- data/spec/extensions/integer_spec.rb +0 -18
- data/spec/extensions/nil_spec.rb +0 -34
- data/spec/extensions/numeric_spec.rb +0 -14
- data/spec/extensions/string_spec.rb +0 -114
- data/spec/extensions/time_spec.rb +0 -16
- data/spec/extensions/true_spec.rb +0 -11
- data/spec/spec_helper.rb +0 -86
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 36e22b14857c9ce862d6610260ebf28c314982649a0a69e6e04cf37bd74fad25
|
|
4
|
+
data.tar.gz: 1002cd447ad89971c298c3eeb3f21069302491667781546c82de05b28beb3521
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 60992cd05bf21a44458666b8bdd8d6e6e91360c53f259f930421b05ed1701b0e9f6b028c28842793007be1312e9c28a6036de6b5484ccae3a967b0a692b311bf
|
|
7
|
+
data.tar.gz: 52bf4954ecfcd7a36f1efb02a4b5fd72e671242ce5df1c95ae96b2150915b3b61abfbd4aec5fc53df9af512ec80d4a031b6c4d6cb90168590f6dfba5c8c6886f
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.6.0
|
|
4
|
+
|
|
5
|
+
- Support Ruby 4.0: `required_ruby_version` is now `>= 3.2` (was `~> 3.0`, which
|
|
6
|
+
excluded Ruby 4).
|
|
7
|
+
- Drop support for Ruby 3.0 and 3.1, which have reached end of life.
|
|
8
|
+
- Limit ActiveSupport to `>= 6.0, < 9`.
|
|
9
|
+
- Gemspec: package files with `Dir` instead of `git ls-files`, remove the
|
|
10
|
+
deprecated `test_files`, require MFA for publishing, and add source, changelog
|
|
11
|
+
and bug tracker links.
|
|
12
|
+
- Replace the Travis build, which no longer ran, with GitHub Actions on Ruby 3.2
|
|
13
|
+
through 4.0.
|
|
14
|
+
- Update RuboCop to 1.92 and rubocop-rspec to 3.10.
|
|
15
|
+
- Fix a spec for `nil + other` that didn't actually test it.
|
|
16
|
+
|
|
17
|
+
## 1.5.0
|
|
18
|
+
|
|
19
|
+
- Drop support for Ruby 2.
|
data/README.md
CHANGED
|
@@ -1,92 +1,146 @@
|
|
|
1
1
|
# DmRubyExtensions
|
|
2
2
|
|
|
3
3
|
[](http://badge.fury.io/rb/dm_ruby_extensions)
|
|
4
|
-
[](https://github.com/digitalmoksha/dm_ruby_extensions/actions/workflows/ci.yml)
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
A small set of convenience methods added to Ruby's core classes (`String`, `Hash`,
|
|
7
|
+
`Array`, `Date` and others). It's used by the digitalMoksha gems, such as
|
|
8
|
+
[moksha_cms](https://gitlab.com/moksha_cms/moksha_cms), for formatting names and
|
|
9
|
+
titles, building CSS and URLs, reading Rails date params, and similar everyday jobs.
|
|
7
10
|
|
|
8
|
-
##
|
|
9
|
-
|
|
10
|
-
Add this line to your application's Gemfile:
|
|
11
|
-
|
|
12
|
-
gem 'dm_ruby_extensions'
|
|
13
|
-
|
|
14
|
-
And then execute:
|
|
15
|
-
|
|
16
|
-
$ bundle
|
|
17
|
-
|
|
18
|
-
Or install it yourself as:
|
|
19
|
-
|
|
20
|
-
$ gem install dm_ruby_extensions
|
|
21
|
-
|
|
22
|
-
## Usage
|
|
23
|
-
|
|
24
|
-
#### Array
|
|
25
|
-
|
|
26
|
-
* extract_options!
|
|
27
|
-
* closest_max
|
|
28
|
-
* xss_aware_join
|
|
29
|
-
* css_join
|
|
30
|
-
|
|
31
|
-
#### Date
|
|
32
|
-
|
|
33
|
-
* to_age
|
|
34
|
-
* localize
|
|
11
|
+
## Requirements
|
|
35
12
|
|
|
36
|
-
|
|
13
|
+
- Ruby 3.2 or later (CI covers 3.2 through 4.0)
|
|
14
|
+
- ActiveSupport 6.0 or later
|
|
37
15
|
|
|
38
|
-
|
|
39
|
-
|
|
16
|
+
Requiring the gem also loads `active_support/core_ext`. The `localize` methods use
|
|
17
|
+
`I18n`, which comes with ActiveSupport.
|
|
40
18
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
* factorial
|
|
44
|
-
* as_boolean
|
|
45
|
-
|
|
46
|
-
#### Hash
|
|
47
|
-
|
|
48
|
-
* convert_date
|
|
49
|
-
* convert_datetime
|
|
50
|
-
* url_query_string
|
|
51
|
-
* rekey
|
|
52
|
-
* rekey!
|
|
53
|
-
|
|
54
|
-
#### Nil
|
|
55
|
-
|
|
56
|
-
* to_s_default
|
|
57
|
-
* as_boolean
|
|
58
|
-
* to_age
|
|
59
|
-
* sql_wildcard
|
|
60
|
-
|
|
61
|
-
#### Numeric
|
|
62
|
-
|
|
63
|
-
* percent_of
|
|
64
|
-
|
|
65
|
-
#### String
|
|
66
|
-
|
|
67
|
-
* to_s_default
|
|
68
|
-
* as_boolean
|
|
69
|
-
* as_css_size
|
|
70
|
-
* sql_wildcard
|
|
71
|
-
* replace_non_alphanumeric
|
|
72
|
-
* expand_url
|
|
73
|
-
* absolute_url?
|
|
74
|
-
* smart_titlecase
|
|
75
|
-
* smart_capitalize
|
|
76
|
-
* smart_capitalize!
|
|
77
|
-
* smart_truncate
|
|
78
|
-
* name_case
|
|
79
|
-
* name_case!
|
|
19
|
+
## Installation
|
|
80
20
|
|
|
81
|
-
|
|
21
|
+
Add it to your Gemfile:
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
gem 'dm_ruby_extensions'
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
and run `bundle install`. In a Rails app it's loaded by Bundler; elsewhere, add
|
|
28
|
+
`require 'dm_ruby_extensions'`.
|
|
29
|
+
|
|
30
|
+
## What it adds
|
|
31
|
+
|
|
32
|
+
### String
|
|
33
|
+
|
|
34
|
+
| Method | Description |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `to_s_default(default = 'n/a')` | The string, or `default` if it's empty or only whitespace |
|
|
37
|
+
| `as_boolean` | `true` for `'true'`, `'yes'` or `'1'`, otherwise `false` |
|
|
38
|
+
| `as_css_size` | Adds `px` unless the value already has `px`, `%` or `em`, or is `auto`/`inherit` |
|
|
39
|
+
| `sql_wildcard` | Wraps the string in `%` for a SQL `LIKE` |
|
|
40
|
+
| `replace_non_alphanumeric(replacement = '')` | Replaces everything except letters, digits, `_`, `.` and `-` |
|
|
41
|
+
| `sanitize_filename` | Strips any path (Unix or Windows) and replaces unsafe characters with `_` |
|
|
42
|
+
| `expand_url(path = '')` | Prefixes a relative URL with `path`; absolute URLs are returned unchanged |
|
|
43
|
+
| `absolute_url?` | `true` if the string contains `://` or starts with `/` |
|
|
44
|
+
| `smart_titlecase` | Title case that keeps small words lowercase (Ruby port of John Gruber's TitleCase) |
|
|
45
|
+
| `smart_capitalize` / `smart_capitalize!` | Capitalizes the first real letter, leaving words like `iPhone` alone |
|
|
46
|
+
| `smart_truncate(words: 12)` / `smart_truncate(sentences: n)` | Truncates by words or sentences and appends `...` |
|
|
47
|
+
| `name_case` / `name_case!` | Properly cases names, e.g. `McDonald`, `O'Brien` (port of Lingua::EN::NameCase) |
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
'300'.as_css_size #=> "300px"
|
|
51
|
+
'images/logo.png'.expand_url('/assets') #=> "/assets/images/logo.png"
|
|
52
|
+
'C:\docs\my report.pdf'.sanitize_filename #=> "my_report.pdf"
|
|
53
|
+
'the lord of the rings'.smart_titlecase #=> "The Lord of the Rings"
|
|
54
|
+
'one two three four five'.smart_truncate(words: 3) #=> "one two three..."
|
|
55
|
+
'MCDONALD'.name_case #=> "McDonald"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Hash
|
|
59
|
+
|
|
60
|
+
| Method | Description |
|
|
61
|
+
|---|---|
|
|
62
|
+
| `convert_date(attribute)` | Builds a `Date` from Rails date-select params (`attr(1i)`–`attr(3i)`), or `nil` |
|
|
63
|
+
| `convert_datetime(attribute)` | Builds a local `Time` from Rails datetime-select params (`attr(1i)`–`attr(5i)`), or `nil` |
|
|
64
|
+
| `url_query_string(leading_slash = true)` | Turns the hash into a query string, e.g. `"/?page=2&q=yoga"` |
|
|
65
|
+
| `rekey` / `rekey!` | Renames keys with a key map or a block; with neither, symbolizes all keys (from [Facets](https://github.com/rubyworks/facets)) |
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
params = { 'start_date(1i)' => '2026', 'start_date(2i)' => '11', 'start_date(3i)' => '8' }
|
|
69
|
+
params.convert_date(:start_date) #=> Sun, 08 Nov 2026
|
|
70
|
+
{ page: 2, q: 'yoga' }.url_query_string #=> "/?page=2&q=yoga"
|
|
71
|
+
{ a: 1, b: 2 }.rekey(a: 'x') # 'x' => 1, :b => 2
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Array
|
|
75
|
+
|
|
76
|
+
| Method | Description |
|
|
77
|
+
|---|---|
|
|
78
|
+
| `extract_options!` | Removes and returns a trailing options hash, or `{}` |
|
|
79
|
+
| `closest_max(value)` | The largest element that is less than or equal to `value` |
|
|
80
|
+
| `xss_aware_join(delimiter = '')` | Joins into an `html_safe` string, escaping elements that aren't already safe |
|
|
81
|
+
| `css_join` | Joins CSS class names, skipping `nil` and empty strings; returns `nil` if nothing is left, so Rails leaves the attribute out |
|
|
82
|
+
|
|
83
|
+
```ruby
|
|
84
|
+
[0, 5, 7, 8, 11, 16].closest_max(6) #=> 5
|
|
85
|
+
['btn', nil, '', 'btn-primary'].css_join #=> "btn btn-primary"
|
|
86
|
+
[nil, ''].css_join #=> nil
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Date, DateTime and Time
|
|
90
|
+
|
|
91
|
+
| Method | Description |
|
|
92
|
+
|---|---|
|
|
93
|
+
| `Date#to_age`, `DateTime#to_age` | Age in whole years, e.g. from a birth date |
|
|
94
|
+
| `Date#to_index`, `DateTime#to_index` | A sortable integer for the day: day of year + (year − 2000) × 1000 |
|
|
95
|
+
| `localize(options = {})` | `I18n.localize(self, ...)`; a string argument is taken as the `format` |
|
|
96
|
+
|
|
97
|
+
### Numbers and booleans
|
|
98
|
+
|
|
99
|
+
| Method | Description |
|
|
100
|
+
|---|---|
|
|
101
|
+
| `Integer#factorial` | `5.factorial #=> 120` |
|
|
102
|
+
| `Integer#as_boolean` | `true` for positive numbers, otherwise `false` |
|
|
103
|
+
| `Numeric#percent_of(total, precision = 0)` | `25.percent_of(80) #=> 31`; returns `0` when `total` is zero |
|
|
104
|
+
| `TrueClass#as_boolean`, `FalseClass#as_boolean` | Return themselves, so `as_boolean` works on any of these values |
|
|
105
|
+
|
|
106
|
+
### nil
|
|
107
|
+
|
|
108
|
+
`nil` gets the same helpers, so you don't have to check for it first:
|
|
109
|
+
|
|
110
|
+
| Method | Returns |
|
|
111
|
+
|---|---|
|
|
112
|
+
| `to_s_default(default = 'n/a')` | `default` |
|
|
113
|
+
| `as_boolean` | `false` |
|
|
114
|
+
| `to_age` | `0` |
|
|
115
|
+
| `sql_wildcard` | `'%'` (matches everything) |
|
|
116
|
+
| `utc` | `''` |
|
|
117
|
+
| `+(other)` | `other`, so `nil + 5 #=> 5` |
|
|
118
|
+
|
|
119
|
+
## Development
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
bundle install
|
|
123
|
+
bundle exec rspec
|
|
124
|
+
bundle exec rubocop
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
CI runs the specs on Ruby 3.2 through 4.0 (plus ruby-head) on Linux and macOS, and
|
|
128
|
+
runs RuboCop, for every pull request and push to `master`.
|
|
129
|
+
|
|
130
|
+
To release a new version, update `lib/dm_ruby_extensions/version.rb` and
|
|
131
|
+
`CHANGELOG.md`, then:
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
gem build dm_ruby_extensions.gemspec
|
|
135
|
+
gem push dm_ruby_extensions-<version>.gem
|
|
136
|
+
```
|
|
82
137
|
|
|
83
|
-
|
|
138
|
+
## Contributing
|
|
84
139
|
|
|
140
|
+
Bug reports and pull requests are welcome at
|
|
141
|
+
<https://github.com/digitalmoksha/dm_ruby_extensions>. Please include specs for any
|
|
142
|
+
change.
|
|
85
143
|
|
|
86
|
-
##
|
|
144
|
+
## License
|
|
87
145
|
|
|
88
|
-
|
|
89
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
90
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
91
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
|
92
|
-
5. Create new Pull Request
|
|
146
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
#------------------------------------------------------------------------------
|
|
2
4
|
class Array
|
|
3
|
-
|
|
4
|
-
#
|
|
5
|
+
# Extract options from a set of arguments. Removes and returns the last element
|
|
6
|
+
# in the array if it's a hash, otherwise returns a blank hash.
|
|
5
7
|
#
|
|
6
8
|
# def options(*args)
|
|
7
9
|
# args.extract_options!
|
|
@@ -19,7 +21,7 @@ class Array
|
|
|
19
21
|
# [0,5,7,8,11,16].closest_max(7) => 7
|
|
20
22
|
#------------------------------------------------------------------------------
|
|
21
23
|
def closest_max(value)
|
|
22
|
-
self.select{|item| item <= value}.max
|
|
24
|
+
self.select { |item| item <= value }.max
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
# able to join safe and unsafe strings
|
|
@@ -27,7 +29,7 @@ class Array
|
|
|
27
29
|
def xss_aware_join(delimiter = '')
|
|
28
30
|
''.html_safe.tap do |str|
|
|
29
31
|
each_with_index do |element, i|
|
|
30
|
-
str << delimiter if i
|
|
32
|
+
str << delimiter if i.positive?
|
|
31
33
|
str << element
|
|
32
34
|
end
|
|
33
35
|
end
|
|
@@ -38,8 +40,8 @@ class Array
|
|
|
38
40
|
# is an empty string (rails tag methods will not include the
|
|
39
41
|
# attribute if it is nil, which is desirable for cleaner html)
|
|
40
42
|
#------------------------------------------------------------------------------
|
|
41
|
-
def css_join(
|
|
42
|
-
str =
|
|
43
|
+
def css_join(_delimiter = '')
|
|
44
|
+
str = flatten.delete_if { |x| x.nil? || x == '' }.join(' ')
|
|
43
45
|
str == '' ? nil : str
|
|
44
46
|
end
|
|
45
47
|
end
|
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
class Date
|
|
3
4
|
# http://stackoverflow.com/questions/819263/get-persons-age-in-ruby
|
|
4
5
|
#------------------------------------------------------------------------------
|
|
5
6
|
def to_age
|
|
6
7
|
now = Time.now.utc.to_date
|
|
7
|
-
now.year -
|
|
8
|
+
now.year - year - (now.month > month || (now.month == month && now.day >= day) ? 0 : 1)
|
|
8
9
|
end
|
|
9
|
-
|
|
10
|
+
|
|
10
11
|
#------------------------------------------------------------------------------
|
|
11
12
|
def localize(options = {})
|
|
12
|
-
options = {:
|
|
13
|
-
I18n.localize(self, options)
|
|
13
|
+
options = { format: options } if options.instance_of?(String)
|
|
14
|
+
I18n.localize(self, **options)
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
# Create a unique sortable index for this date
|
|
17
18
|
#------------------------------------------------------------------------------
|
|
18
19
|
def to_index
|
|
19
|
-
yday + (year-2000) * 1000
|
|
20
|
+
yday + ((year - 2000) * 1000)
|
|
20
21
|
end
|
|
21
|
-
|
|
22
22
|
end
|
|
23
|
-
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
#------------------------------------------------------------------------------
|
|
2
4
|
class DateTime
|
|
3
|
-
|
|
4
5
|
#------------------------------------------------------------------------------
|
|
5
6
|
def to_age
|
|
6
7
|
(DateTime.now - self).to_i / 365
|
|
@@ -8,15 +9,13 @@ class DateTime
|
|
|
8
9
|
|
|
9
10
|
#------------------------------------------------------------------------------
|
|
10
11
|
def localize(options = {})
|
|
11
|
-
options = {:
|
|
12
|
-
I18n.localize(self, options)
|
|
12
|
+
options = { format: options } if options.instance_of?(String)
|
|
13
|
+
I18n.localize(self, **options)
|
|
13
14
|
end
|
|
14
|
-
|
|
15
|
+
|
|
15
16
|
# Create a unique sortable index for this date
|
|
16
17
|
#------------------------------------------------------------------------------
|
|
17
18
|
def to_index
|
|
18
|
-
yday + (year-2000) * 1000
|
|
19
|
+
yday + ((year - 2000) * 1000)
|
|
19
20
|
end
|
|
20
|
-
|
|
21
21
|
end
|
|
22
|
-
|
|
@@ -1,29 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
#------------------------------------------------------------------------------
|
|
2
4
|
class Hash
|
|
3
|
-
|
|
4
|
-
# takes a Hash (like the params hash), and converts the Rails date attributes
|
|
5
|
+
# takes a Hash (like the params hash), and converts the Rails date attributes
|
|
5
6
|
# to a real Date object.
|
|
6
|
-
# {'start_date(1i)' => 2012, 'start_date(2i)' => 11, 'start_date(3i)' => 23}.convert_date(:start_date)
|
|
7
|
+
# {'start_date(1i)' => 2012, 'start_date(2i)' => 11, 'start_date(3i)' => 23}.convert_date(:start_date)
|
|
7
8
|
#------------------------------------------------------------------------------
|
|
8
9
|
def convert_date(date_symbol_or_string)
|
|
9
10
|
attribute = date_symbol_or_string.to_s
|
|
10
|
-
return nil if self[attribute
|
|
11
|
-
|
|
11
|
+
return nil if self["#{attribute}(1i)"].nil? || self["#{attribute}(2i)"].nil? || self["#{attribute}(3i)"].nil?
|
|
12
|
+
|
|
13
|
+
Date.new(self["#{attribute}(1i)"].to_i, self["#{attribute}(2i)"].to_i, self["#{attribute}(3i)"].to_i)
|
|
12
14
|
end
|
|
13
15
|
|
|
14
|
-
# takes a Hash (like the params hash), and converts the Rails datetime attributes
|
|
16
|
+
# takes a Hash (like the params hash), and converts the Rails datetime attributes
|
|
15
17
|
# to a real Date object.
|
|
16
18
|
#------------------------------------------------------------------------------
|
|
17
19
|
def convert_datetime(date_symbol_or_string)
|
|
18
20
|
attribute = date_symbol_or_string.to_s
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
if self["#{attribute}(1i)"].nil? || self["#{attribute}(2i)"].nil? ||
|
|
22
|
+
self["#{attribute}(3i)"].nil? || self["#{attribute}(4i)"].nil? ||
|
|
23
|
+
self["#{attribute}(5i)"].nil?
|
|
24
|
+
return nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
Time.local(self["#{attribute}(1i)"].to_i, self["#{attribute}(2i)"].to_i, self["#{attribute}(3i)"].to_i,
|
|
28
|
+
self["#{attribute}(4i)"].to_i, self["#{attribute}(5i)"].to_i)
|
|
21
29
|
end
|
|
22
30
|
|
|
23
31
|
# Convert hash of parameters to a query string
|
|
24
32
|
#------------------------------------------------------------------------------
|
|
25
|
-
def url_query_string(leading_slash = true)
|
|
26
|
-
|
|
33
|
+
def url_query_string(leading_slash = true) # rubocop:disable Style/OptionalBooleanParameter
|
|
34
|
+
"#{leading_slash ? '/?' : '?'}#{to_query}"
|
|
27
35
|
end
|
|
28
36
|
|
|
29
37
|
# Borrowed from https://github.com/rubyworks/facets
|
|
@@ -42,7 +50,7 @@ class Hash
|
|
|
42
50
|
# foo.rekey(:b=>:x) #=> { :a =>1, :x=>2 }
|
|
43
51
|
# foo.rekey('foo'=>'bar') #=> { :a =>1, :b=>2 }
|
|
44
52
|
#
|
|
45
|
-
# If a block is given, converts all keys in the Hash
|
|
53
|
+
# If a block is given, converts all keys in the Hash according to the
|
|
46
54
|
# given block procedure.
|
|
47
55
|
#
|
|
48
56
|
# foo = { :name=>'Gavin', :wife=>:Lisa }
|
|
@@ -55,37 +63,36 @@ class Hash
|
|
|
55
63
|
# Raises an ArgumentError if both a +key_map+ and a block are given.
|
|
56
64
|
# If both are needed just call #rekey twice.
|
|
57
65
|
#
|
|
58
|
-
# TODO: If `nil` is returned by block should the key be set to `nil` or the
|
|
66
|
+
# TODO: If `nil` is returned by block should the key be set to `nil` or the original key?
|
|
59
67
|
#
|
|
60
68
|
# CREDIT: Trans, Gavin Kistner
|
|
69
|
+
def rekey(key_map = nil, &block)
|
|
70
|
+
raise ArgumentError, 'argument or block' if key_map && block
|
|
61
71
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if !(key_map or block)
|
|
66
|
-
block = lambda{|k| k.to_sym}
|
|
72
|
+
unless key_map || block
|
|
73
|
+
block = lambda { |k| k.to_sym } # rubocop:disable Style/SymbolProc, Style/Lambda
|
|
67
74
|
end
|
|
68
75
|
|
|
69
76
|
if block
|
|
70
77
|
hash = dup.clear
|
|
71
78
|
if block.arity.abs == 1
|
|
72
79
|
each_pair do |k, v|
|
|
73
|
-
hash[block[k]] = v
|
|
80
|
+
hash[block[k]] = v # hash[block[k] || k] = v
|
|
74
81
|
end
|
|
75
82
|
else
|
|
76
83
|
each_pair do |k, v|
|
|
77
|
-
hash[block[k,v]] = v
|
|
84
|
+
hash[block[k, v]] = v # hash[block[k,v] || k] = v
|
|
78
85
|
end
|
|
79
86
|
end
|
|
80
87
|
else
|
|
81
|
-
#hash = dup.clear # to keep default_proc
|
|
82
|
-
#(keys - key_map.keys).each do |key|
|
|
83
|
-
#
|
|
84
|
-
#end
|
|
85
|
-
#key_map.each do |from, to|
|
|
86
|
-
#
|
|
87
|
-
#end
|
|
88
|
-
hash = dup
|
|
88
|
+
# hash = dup.clear # to keep default_proc
|
|
89
|
+
# (keys - key_map.keys).each do |key|
|
|
90
|
+
# hash[key] = self[key]
|
|
91
|
+
# end
|
|
92
|
+
# key_map.each do |from, to|
|
|
93
|
+
# hash[to] = self[from] if key?(from)
|
|
94
|
+
# end
|
|
95
|
+
hash = dup # to keep default_proc
|
|
89
96
|
key_map.each_pair do |from, to|
|
|
90
97
|
hash[to] = hash.delete(from) if hash.key?(from)
|
|
91
98
|
end
|
|
@@ -102,8 +109,7 @@ class Hash
|
|
|
102
109
|
#
|
|
103
110
|
# CREDIT: Trans, Gavin Kistner
|
|
104
111
|
|
|
105
|
-
def rekey!(key_map=nil, &
|
|
106
|
-
replace(rekey(key_map, &
|
|
112
|
+
def rekey!(key_map = nil, &)
|
|
113
|
+
replace(rekey(key_map, &))
|
|
107
114
|
end
|
|
108
|
-
|
|
109
115
|
end
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
class Integer
|
|
3
4
|
# Factorial of number
|
|
4
5
|
# 5.factorial == 5 x 4 x 3 x 2 x 1 == 120
|
|
5
6
|
#------------------------------------------------------------------------------
|
|
6
7
|
def factorial
|
|
7
|
-
return 1 if
|
|
8
|
+
return 1 if zero?
|
|
9
|
+
|
|
8
10
|
(1..self).inject(:*)
|
|
9
11
|
end
|
|
10
12
|
|
|
11
13
|
#------------------------------------------------------------------------------
|
|
12
14
|
def as_boolean
|
|
13
|
-
|
|
15
|
+
positive?
|
|
14
16
|
end
|
|
15
|
-
|
|
16
17
|
end
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# If nil, then return a default string
|
|
2
4
|
#------------------------------------------------------------------------------
|
|
3
|
-
class NilClass
|
|
4
|
-
|
|
5
|
+
class NilClass # :nodoc:
|
|
5
6
|
#------------------------------------------------------------------------------
|
|
6
7
|
def to_s_default(default_str = 'n/a')
|
|
7
8
|
default_str
|
|
@@ -11,7 +12,7 @@ class NilClass #:nodoc:
|
|
|
11
12
|
def as_boolean
|
|
12
13
|
false
|
|
13
14
|
end
|
|
14
|
-
|
|
15
|
+
|
|
15
16
|
#------------------------------------------------------------------------------
|
|
16
17
|
def to_age
|
|
17
18
|
0
|
|
@@ -19,18 +20,17 @@ class NilClass #:nodoc:
|
|
|
19
20
|
|
|
20
21
|
#------------------------------------------------------------------------------
|
|
21
22
|
def sql_wildcard
|
|
22
|
-
|
|
23
|
+
'%'
|
|
23
24
|
end
|
|
24
|
-
|
|
25
|
+
|
|
25
26
|
#------------------------------------------------------------------------------
|
|
26
27
|
def utc
|
|
27
|
-
|
|
28
|
+
''
|
|
28
29
|
end
|
|
29
|
-
|
|
30
|
+
|
|
30
31
|
# if nil + something, just return something
|
|
31
32
|
#------------------------------------------------------------------------------
|
|
32
|
-
def +(
|
|
33
|
-
|
|
33
|
+
def +(other)
|
|
34
|
+
other
|
|
34
35
|
end
|
|
35
|
-
|
|
36
|
-
end
|
|
36
|
+
end
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
class Numeric
|
|
2
4
|
#------------------------------------------------------------------------------
|
|
3
|
-
def percent_of(
|
|
4
|
-
|
|
5
|
+
def percent_of(num, precision = 0)
|
|
6
|
+
num.zero? ? 0 : (to_f / num * 100.0).round(precision)
|
|
5
7
|
end
|
|
6
8
|
end
|