useful_utilities 5.4.5

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e5e4bbec43984ce6756ade1190a5f21e4dfbaf5e
4
+ data.tar.gz: 236d91abef2bedcfaaab5e49c7c78cc998a5eedd
5
+ SHA512:
6
+ metadata.gz: 79972ec7576ea4d937a16a113cdf10082c7bad7a0b415b46a6adf56ead972caf76c3edc17286e6640c84b726fc48884726ba276c9647f20358b97b04a4cc94d7
7
+ data.tar.gz: 35b254e47c6638587ae79491a8eb013cbc39ea5fd5503a668f7847588eee3a8d2af74d32538e7fd52a0bb9f21236b0daf5048f73d4480ac74a4fdc1c92a58cb2
data/README.md ADDED
@@ -0,0 +1,14 @@
1
+ ## UsefulUtilities
2
+
3
+ A collection of useful utilities
4
+
5
+ This package include next tools with new namespaces:
6
+
7
+ Api Utilities => UsefulUtilities::Api
8
+ AR Utilities => UsefulUtilities::AR
9
+ Hash Utilities => UsefulUtilities::Hash
10
+ Size Utilities => UsefulUtilities::Size
11
+ Numeric Utilities => UsefulUtilities::Numeric
12
+ Time Utilities => UsefulUtilities::Time
13
+ YAML Utilities => UsefulUtilities::YAML
14
+ I18n Utilities => UsefulUtilities::I18n
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env rake
2
+
3
+ begin
4
+ require 'bundler/setup'
5
+ require 'rubygems'
6
+ rescue LoadError
7
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
8
+ end
9
+
10
+ begin
11
+ require 'rdoc/task'
12
+ rescue LoadError
13
+ require 'rdoc/rdoc'
14
+ require 'rake/rdoctask'
15
+ RDoc::Task = Rake::RDocTask
16
+ end
17
+
18
+ APP_RAKEFILE = File.expand_path('../spec/dummy/Rakefile', __FILE__)
19
+ load 'rails/tasks/engine.rake'
20
+
21
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,26 @@
1
+ require 'socket'
2
+ require 'timeout'
3
+
4
+ module UsefulUtilities
5
+ module Api
6
+ extend self
7
+
8
+ RESCUE_PORT_OPEN_EXCEPTIONS = [Errno::ENETUNREACH, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError, Timeout::Error].freeze
9
+
10
+ def convert_limit(value)
11
+ value == Float::INFINITY ? false : value
12
+ end
13
+
14
+ # checks if a port is open or not on a remote host
15
+ def port_open?(ip, port, sleep_time: 1, max_attempts: 3)
16
+ try_to(max_attempts: max_attempts, sleep_time: sleep_time, rescue_what: RESCUE_PORT_OPEN_EXCEPTIONS) do
17
+ Timeout::timeout(sleep_time) do
18
+ TCPSocket.new(ip, port).close
19
+ true
20
+ end
21
+ end
22
+ rescue *RESCUE_PORT_OPEN_EXCEPTIONS
23
+ false
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,147 @@
1
+ require 'active_record'
2
+ require 'active_support/all'
3
+
4
+ module UsefulUtilities
5
+ module AR
6
+ module Methods
7
+ def foreign_key(association_class)
8
+ reflections.values.find do |reflection|
9
+ reflection.class_name == association_class.name
10
+ end.foreign_key
11
+ end
12
+ end
13
+
14
+ extend self
15
+
16
+ NESTED_ASSOCIATIONS = %i( has_one has_many )
17
+ BASE_ERROR_KEY = :base
18
+ TYPE_SUFFIX = '%s_type'
19
+ ID_SUFFIX = '%s_id'
20
+
21
+ def value_to_integer(value)
22
+ return 0 if value.nil?
23
+ return 0 if value == false
24
+ return 1 if value == true
25
+
26
+ ActiveRecord::Type::Integer.new.type_cast_from_database(value)
27
+ end
28
+
29
+ def value_to_decimal(value)
30
+ return BigDecimal.new(0) if value.nil?
31
+
32
+ ActiveRecord::Type::Decimal.new.type_cast_from_database(value)
33
+ end
34
+
35
+ def value_to_boolean(value)
36
+ return false if value.nil?
37
+
38
+ ActiveRecord::Type::Boolean.new.type_cast_from_database(value)
39
+ end
40
+
41
+ def boolean_to_float(value)
42
+ value ? 1.0 : 0.0
43
+ end
44
+
45
+ def deep_validation(record)
46
+ record.valid?
47
+ nested_associations_validation(record)
48
+ end
49
+
50
+ def nested_associations_validation(record, nested = false)
51
+ record.class.reflections.each do |name, reflection|
52
+ next unless NESTED_ASSOCIATIONS.include?(reflection.macro)
53
+
54
+ association_records = Array(record.public_send(name))
55
+ error_key = nested ? BASE_ERROR_KEY : name
56
+ record.errors.delete(name)
57
+
58
+ association_records.each do |nested_record|
59
+ next unless nested_record.changed?
60
+ nested_associations_validation(nested_record, :nested)
61
+ nested_record.errors.full_messages.each { |message| record.errors[error_key] << message }
62
+ end
63
+ end
64
+ end
65
+
66
+ def by_polymorphic(scope, key, value)
67
+ type = to_polymorphic_type(value)
68
+ type_column, id_column = TYPE_SUFFIX % key, ID_SUFFIX % key
69
+ scope.where(type_column => type, id_column => value)
70
+ end
71
+
72
+ def to_polymorphic_type(value)
73
+ klass =
74
+ if value.is_a?(Class) || value.nil? then value
75
+ elsif value.respond_to?(:klass) then value.klass
76
+ else value.class
77
+ end
78
+
79
+ klass.respond_to?(:base_class) ? klass.base_class : klass
80
+ end
81
+
82
+ def [](klass, *columns)
83
+ columns.map { |column| "#{ klass.table_name }.#{ column }" }.join(', ')
84
+ end
85
+
86
+ def asc(klass, column)
87
+ "#{ self[klass, column] } ASC"
88
+ end
89
+
90
+ def desc(klass, column)
91
+ "#{ self[klass, column] } DESC"
92
+ end
93
+
94
+ def older_than(scope, _value)
95
+ value = _value.is_a?(ActiveRecord::Base) ? _value.id : _value
96
+ value.present? ? scope.where("#{ self[scope, :id] } < ?", value) : scope
97
+ end
98
+
99
+ def null_to_zero(*args)
100
+ sql_column =
101
+ case args.size
102
+ when 1 then args.first
103
+ when 2 then self[args[0], args[1]]
104
+ else
105
+ raise ArgumentError, "wrong number of arguments (#{ args.size } for 1..2)"
106
+ end
107
+
108
+ "COALESCE(#{ sql_column }, 0)"
109
+ end
110
+
111
+ def ceil(value)
112
+ "CEILING(#{value})"
113
+ end
114
+
115
+ def sql_sum(*args, result)
116
+ "SUM(#{ null_to_zero(*args) }) AS #{ result }"
117
+ end
118
+
119
+ # Can be used for not NULL columns only
120
+ # sum_by_columns(Virtual, :column_1, :column2, column3: :column3_alias...)
121
+ def sum_by_columns(scope, *all_columns)
122
+ columns = all_columns.flatten
123
+ columns_with_aliases = columns.extract_options!
124
+
125
+ sql_query =
126
+ columns.reduce(columns_with_aliases) { |res, column| res.merge!(column => column) }.
127
+ map { |column, column_alias| "SUM(#{ column }) AS #{ column_alias }" }.join(', ')
128
+
129
+ scope.select(sql_query).first
130
+ end
131
+
132
+ def count(table, column, result)
133
+ "COUNT(#{ self[table, column] }) AS #{ result }"
134
+ end
135
+
136
+ def delete_dependents(owner, self_class, dependent_class)
137
+ dependent_fk = dependent_class.foreign_key(self_class)
138
+ self_fk = self_class.foreign_key(owner.class)
139
+
140
+ "DELETE #{dependent_class.table_name}
141
+ FROM #{dependent_class.table_name}
142
+ INNER JOIN #{self_class.table_name}
143
+ ON #{self[dependent_class, dependent_fk]} = #{self[self_class, :id]}
144
+ WHERE #{self[self_class, self_fk]} = #{owner.id}"
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,49 @@
1
+ module UsefulUtilities
2
+ class CentOSVersion
3
+ attr_reader :version
4
+
5
+ def initialize(version)
6
+ @version = version.to_i
7
+ end
8
+
9
+ class << self
10
+ def centos5?(*args)
11
+ new(*args).centos5?
12
+ end
13
+ alias_method :five?, :centos5?
14
+
15
+ def centos6?(*args)
16
+ new(*args).centos6?
17
+ end
18
+ alias_method :six?, :centos6?
19
+
20
+ def centos7?(*args)
21
+ new(*args).centos7?
22
+ end
23
+ alias_method :seven?, :centos7?
24
+
25
+ def not_centos5?(*args)
26
+ new(*args).not_centos5?
27
+ end
28
+ end
29
+
30
+ def centos5?
31
+ version == 5
32
+ end
33
+ alias_method :five?, :centos5?
34
+
35
+ def centos6?
36
+ version == 6
37
+ end
38
+ alias_method :six?, :centos6?
39
+
40
+ def centos7?
41
+ version == 7
42
+ end
43
+ alias_method :seven?, :centos7?
44
+
45
+ def not_centos5?
46
+ !centos5?
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,29 @@
1
+ module UsefulUtilities
2
+ module Hash
3
+ extend self
4
+
5
+ def sum_values(*list)
6
+ collect_keys(*list).inject({}) do |result, key|
7
+ result[key] = 0
8
+ list.each { |item| result[key] += item[key] if item.has_key?(key) }
9
+
10
+ result
11
+ end
12
+ end
13
+
14
+ def group_by_keys(*list)
15
+ collect_keys(*list).inject({}) do |result, key|
16
+ result[key] = []
17
+ list.each { |item| result[key] << item[key] if item.has_key?(key) }
18
+
19
+ result
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def collect_keys(*list)
26
+ list.inject([]) { |result, item| result |= item.keys }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,16 @@
1
+ module UsefulUtilities
2
+ module I18n
3
+ extend self
4
+
5
+ def humanize_type(object)
6
+ klass = case object
7
+ when Class then object
8
+ when object.respond_to?(:klass) then object.klass
9
+ else
10
+ object.class
11
+ end
12
+
13
+ klass.respond_to?(:model_name) ? klass.model_name.human : klass.to_s.underscore.humanize
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,52 @@
1
+ module UsefulUtilities
2
+ module Numeric
3
+ extend self
4
+
5
+ ZERO = 0
6
+ THOUSAND = 1_000
7
+ MILLION = 1_000_000
8
+ BILLION = 1_000_000_000
9
+
10
+ def positive_or_zero(value)
11
+ (value > ZERO) ? value : ZERO
12
+ end
13
+
14
+ def float_or_integer(value)
15
+ value == value.to_i ? value.to_i : value
16
+ end
17
+
18
+ def to_decimal(value, scale: nil)
19
+ result = value.to_f.to_d
20
+
21
+ scale ? result.round(scale) : result
22
+ end
23
+
24
+ # @note: used SI metric prefixes http://en.wikipedia.org/wiki/SI_prefix
25
+ def to_kilo(value, unit)
26
+ if unit == :M then value * THOUSAND
27
+ elsif unit == :G then value * MILLION
28
+ else unsupported_unit!(unit)
29
+ end
30
+ end
31
+
32
+ def to_giga(value, unit)
33
+ if unit == :k then value.fdiv(MILLION)
34
+ elsif unit == :M then value.fdiv(THOUSAND)
35
+ else unsupported_unit!(unit)
36
+ end
37
+ end
38
+
39
+ def to_number(value, unit)
40
+ if unit == :M then value * MILLION
41
+ elsif unit == :G then value * BILLION
42
+ else unsupported_unit!(unit)
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def unsupported_unit!(unit)
49
+ raise ArgumentError.new("Unsupported unit - #{ unit }")
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,72 @@
1
+ module UsefulUtilities
2
+ class RedhatRelease
3
+ LEGACY_DISTRO_TEMPLATE = 'centos%{major_version}'.freeze
4
+
5
+ VERSION_SEPARATOR = '.'.freeze # this may change to "dot" and "hyphen" if we allow not only final releases(beta, custom git builds, etc)
6
+ VERSION_SEPARATOR_REGEXP = Regexp.escape(VERSION_SEPARATOR).freeze # regexp to match single "dot" character
7
+
8
+ VERSION_REGEXP = %r{ # /etc/redhat-release samples: "CentOS Linux release 7.1.1503 (Core)", "Red Hat Enterprise Linux Server release 7.2 (Maipo)"
9
+ (?<=[[:space:]]) # positive lookbehind assertion: ensures that the preceding character matches single "space" character, but doesn't include this character in the matched text
10
+ (?<major_version>[[:digit:]]) # :major_version named capture group; it matches single digits
11
+ #{VERSION_SEPARATOR_REGEXP} # regexp for separator of version parts
12
+ (?<minor_version>[[:digit:]]+) # :minor_version named capture group; it matches one or more sequential digits
13
+ (?: # grouping without capturing; "monthstamp" version part don't exist for versions of Centos older then 7
14
+ #{VERSION_SEPARATOR_REGEXP} # regexp for separator of version parts
15
+ (?<monthstamp>[[:digit:]]{4}) # :monthstamp named capture group; it matches 4 sequential digits
16
+ )? # zero or one times quantifier(repetition metacharacter)
17
+ (?=[[:space:]]) # positive lookahead assertion: ensures that the following character matches single "space" character, but doesn't include this character in the matched text
18
+ }x.freeze
19
+
20
+ DEFAULT_VERSION_ARR = [6, 0].freeze
21
+
22
+ attr_reader :release_string
23
+
24
+ def initialize(release_string)
25
+ @release_string = release_string.to_s
26
+ end
27
+
28
+ def self.major_version(*args)
29
+ new(*args).major_version
30
+ end
31
+
32
+ def self.legacy_distro(ver)
33
+ LEGACY_DISTRO_TEMPLATE % { major_version: ver }
34
+ end
35
+
36
+ def major_version
37
+ version_arr[0]
38
+ end
39
+
40
+ def minor_version
41
+ version_arr[1]
42
+ end
43
+
44
+ def monthstamp
45
+ version_arr[2]
46
+ end
47
+
48
+ def version_string
49
+ version_arr.join(VERSION_SEPARATOR)
50
+ end
51
+
52
+ private
53
+
54
+ def version_arr
55
+ @version_arr ||= version_match.present? ? match_version_arr : DEFAULT_VERSION_ARR
56
+ end
57
+
58
+ def match_version_arr
59
+ @match_version_arr ||= [
60
+ version_match[:major_version],
61
+ version_match[:minor_version],
62
+ version_match[:monthstamp]
63
+ ].compact.map(&:to_i)
64
+ end
65
+
66
+ def version_match
67
+ return @version_match if defined?(@version_match)
68
+
69
+ @version_match = VERSION_REGEXP.match(release_string)
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,92 @@
1
+ require_relative 'standard/decimal'
2
+
3
+ module UsefulUtilities
4
+ module Size
5
+ module Bit
6
+ # @note: used SI standard http://en.wikipedia.org/wiki/Binary_prefix
7
+ # Decimal
8
+ # 1 K = 1000
9
+ include UsefulUtilities::Size::Standard::Decimal
10
+
11
+ def to_terabits(size, unit)
12
+ to_tera(size, bit_prefix(unit))
13
+ end
14
+
15
+ def to_gigabits(size, unit)
16
+ to_giga(size, bit_prefix(unit))
17
+ end
18
+
19
+ def to_megabits(size, unit)
20
+ to_mega(size, bit_prefix(unit))
21
+ end
22
+
23
+ def to_kilobits(size, unit)
24
+ to_kilo(size, bit_prefix(unit))
25
+ end
26
+
27
+ def to_bits(size, unit)
28
+ to_decimal_bi(size, bit_prefix(unit))
29
+ end
30
+
31
+ # Convert bits to manually defined format
32
+ # by using parameter 'unit'
33
+ # ATTENTION: by default round is eq to 3 digits
34
+ def bits_to_human_size(size, unit, rounder = 3)
35
+ case unit
36
+ when :bit then size.round(rounder)
37
+ when :kbit then to_kilobits(size, :bit).round(rounder)
38
+ when :Mbit then to_megabits(size, :bit).round(rounder)
39
+ when :Gbit then to_gigabits(size, :bit).round(rounder)
40
+ when :Tbit then to_terabits(size, :bit).round(rounder)
41
+ else unsupported_unit!(unit)
42
+ end
43
+ end
44
+
45
+ # Ignore any fractional part of the number
46
+ # Bit can be only integer !!!
47
+ def suitable_unit_for_bits(value)
48
+ return not_integer!(value) unless value.is_a?(Integer)
49
+ return not_positive_integer!(value) unless value > -1
50
+
51
+ if value.to_s.length <= 3 then :bit
52
+ elsif value.to_s.length <= 6 then :kbit
53
+ elsif value.to_s.length <= 9 then :Mbit
54
+ elsif value.to_s.length <= 12 then :Gbit
55
+ else :Tbit
56
+ end
57
+ end
58
+
59
+ def bits_per_sec_to_human_readable(value_in_bits)
60
+ unit = suitable_unit_for_bits(value_in_bits)
61
+ value = bits_to_human_size(value_in_bits, unit.to_sym)
62
+
63
+ "#{value} #{unit}/s"
64
+ end
65
+
66
+ private
67
+
68
+ def bit_prefix(unit)
69
+ case unit
70
+ when :bit then :B
71
+ when :kbit then :KB
72
+ when :Mbit then :MB
73
+ when :Gbit then :GB
74
+ when :Tbit then :TB
75
+ else unsupported_unit!(unit)
76
+ end
77
+ end
78
+
79
+ def unsupported_unit!(unit)
80
+ raise ArgumentError.new("Unsupported unit - #{ unit }")
81
+ end
82
+
83
+ def not_integer!(value)
84
+ raise ArgumentError.new("#{value } is not integer")
85
+ end
86
+
87
+ def not_positive_integer!(value)
88
+ raise ArgumentError.new("#{value } is not positive integer")
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,69 @@
1
+ require_relative 'standard/binary'
2
+
3
+ module UsefulUtilities
4
+ module Size
5
+ module Byte
6
+ # @note: used ISO standard http://en.wikipedia.org/wiki/Binary_prefix
7
+ # Binary
8
+ # 1 K = 1024
9
+ include UsefulUtilities::Size::Standard::Binary
10
+
11
+ HALF_OF_SECTOR = 0.5
12
+
13
+ def to_terabytes(size, unit)
14
+ to_tebi(size, byte_prefix(unit))
15
+ end
16
+
17
+ def to_gigabytes(size, unit)
18
+ to_gibi(size, byte_prefix(unit))
19
+ end
20
+
21
+ def to_megabytes(size, unit)
22
+ to_mebi(size, byte_prefix(unit))
23
+ end
24
+
25
+ def to_kilobytes(size, unit)
26
+ if unit == :sector
27
+ return (size * HALF_OF_SECTOR).round # http://en.wikipedia.org/wiki/Disk_sector
28
+ end
29
+
30
+ to_kibi(size, byte_prefix(unit))
31
+ end
32
+
33
+ def to_bytes(size, unit)
34
+ to_binary_bi(size, byte_prefix(unit))
35
+ end
36
+
37
+ # Convert bytes to manually defined format
38
+ # by using parameter 'unit'
39
+ # ATTENTION: by default round is eq to 3 digits
40
+ def bytes_to_human_size(size, unit, rounder = 3)
41
+ case unit
42
+ when :B then size.round(rounder)
43
+ when :KB then to_kilobytes(size, :B).round(rounder)
44
+ when :MB then to_megabytes(size, :B).round(rounder)
45
+ when :GB then to_gigabytes(size, :B).round(rounder)
46
+ when :TB then to_terabytes(size, :B).round(rounder)
47
+ else unsupported_unit!(unit)
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def byte_prefix(unit)
54
+ case unit
55
+ when :B then :B
56
+ when :KB then :KiB
57
+ when :MB then :MiB
58
+ when :GB then :GiB
59
+ when :TB then :TiB
60
+ else unsupported_unit!(unit)
61
+ end
62
+ end
63
+
64
+ def unsupported_unit!(unit)
65
+ raise ArgumentError.new("Unsupported unit - #{ unit }")
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,33 @@
1
+ require_relative 'standard/decimal'
2
+
3
+ module UsefulUtilities
4
+ module Size
5
+ module CdnSpeed
6
+ # @note: used SI standard http://en.wikipedia.org/wiki/Binary_prefix
7
+ # Decimal
8
+ # 1 K = 1000
9
+ include UsefulUtilities::Size::Standard::Decimal
10
+
11
+ def to_cdn_gbps(speed, unit)
12
+ to_giga(speed, bit_prefix(unit))/8
13
+ end
14
+
15
+ private
16
+
17
+ def bit_prefix(unit)
18
+ case unit
19
+ when :bit then :B
20
+ when :kbit then :KB
21
+ when :Mbit then :MB
22
+ when :Gbit then :GB
23
+ when :Tbit then :TB
24
+ else unsupported_unit!(unit)
25
+ end
26
+ end
27
+
28
+ def unsupported_unit!(unit)
29
+ raise ArgumentError.new("Unsupported unit - #{ unit }")
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,37 @@
1
+ require_relative 'standard/decimal'
2
+
3
+ module UsefulUtilities
4
+ module Size
5
+ module Frequency
6
+ # @note: used SI standard http://en.wikipedia.org/wiki/Binary_prefix
7
+ # Decimal
8
+ # 1 K = 1000
9
+ include UsefulUtilities::Size::Standard::Decimal
10
+
11
+ def to_megahertz(size, unit)
12
+ to_mega(size, frequency_prefix(unit))
13
+ end
14
+
15
+ def to_gigahertz(size, unit)
16
+ to_giga(size, frequency_prefix(unit))
17
+ end
18
+
19
+ private
20
+
21
+ def frequency_prefix(unit)
22
+ case unit
23
+ when :Hz then :B
24
+ when :KHz then :KB
25
+ when :MHz then :MB
26
+ when :GHz then :GB
27
+ when :THz then :TB
28
+ else unsupported_unit!(unit)
29
+ end
30
+ end
31
+
32
+ def unsupported_unit!(unit)
33
+ raise ArgumentError.new("Unsupported unit - #{ unit }")
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,15 @@
1
+ module UsefulUtilities
2
+ module Size
3
+ module Percentage
4
+ HUNDRED = 100
5
+
6
+ def fraction_to_percentage(fraction)
7
+ fraction * HUNDRED
8
+ end
9
+
10
+ def percentage_to_fraction(percentage)
11
+ percentage.fdiv(HUNDRED)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,69 @@
1
+ module UsefulUtilities
2
+ module Size
3
+ module Standard
4
+ module Binary
5
+ # @note: used ISO standard http://en.wikipedia.org/wiki/Binary_prefix
6
+
7
+ KIBI = 1024 # KiB
8
+ MEBI = KIBI ** 2 # MiB
9
+ GIBI = KIBI ** 3 # GiB
10
+ TEBI = KIBI ** 4 # TiB
11
+
12
+ def to_tebi(val, prefix)
13
+ case prefix
14
+ when :B then val.fdiv(TEBI)
15
+ when :KiB then val.fdiv(GIBI)
16
+ when :MiB then val.fdiv(MEBI)
17
+ when :GiB then val.fdiv(KIBI)
18
+ when :TiB then val
19
+ else unsupported_unit!(prefix)
20
+ end
21
+ end
22
+
23
+ def to_gibi(val, prefix)
24
+ case prefix
25
+ when :B then val.fdiv(GIBI)
26
+ when :KiB then val.fdiv(MEBI)
27
+ when :MiB then val.fdiv(KIBI)
28
+ when :GiB then val
29
+ when :TiB then val * KIBI
30
+ else unsupported_unit!(prefix)
31
+ end
32
+ end
33
+
34
+ def to_mebi(val, prefix)
35
+ case prefix
36
+ when :B then val.fdiv(MEBI)
37
+ when :KiB then val.fdiv(KIBI)
38
+ when :MiB then val
39
+ when :GiB then val * KIBI
40
+ when :TiB then val * MEBI
41
+ else unsupported_unit!(prefix)
42
+ end
43
+ end
44
+
45
+ def to_kibi(val, prefix)
46
+ case prefix
47
+ when :B then val.fdiv(KIBI)
48
+ when :KiB then val
49
+ when :MiB then val * KIBI
50
+ when :GiB then val * MEBI
51
+ when :TiB then val * GIBI
52
+ else unsupported_unit!(prefix)
53
+ end
54
+ end
55
+
56
+ def to_binary_bi(val, prefix)
57
+ case prefix
58
+ when :B then val
59
+ when :KiB then val * KIBI
60
+ when :MiB then val * MEBI
61
+ when :GiB then val * GIBI
62
+ when :TiB then val * TEBI
63
+ else unsupported_unit!(prefix)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,69 @@
1
+ module UsefulUtilities
2
+ module Size
3
+ module Standard
4
+ module Decimal
5
+ # @note: used SI standard http://en.wikipedia.org/wiki/Binary_prefix
6
+
7
+ KILO = 1000 # KB
8
+ MEGA = KILO ** 2 # MB
9
+ GIGA = KILO ** 3 # GB
10
+ TERA = KILO ** 4 # TB
11
+
12
+ def to_tera(val, prefix)
13
+ case prefix
14
+ when :B then val.fdiv(TERA)
15
+ when :KB then val.fdiv(GIGA)
16
+ when :MB then val.fdiv(MEGA)
17
+ when :GB then val.fdiv(KILO)
18
+ when :TB then val
19
+ else unsupported_unit!(prefix)
20
+ end
21
+ end
22
+
23
+ def to_giga(val, prefix)
24
+ case prefix
25
+ when :B then val.fdiv(GIGA)
26
+ when :KB then val.fdiv(MEGA)
27
+ when :MB then val.fdiv(KILO)
28
+ when :GB then val
29
+ when :TB then val * KILO
30
+ else unsupported_unit!(prefix)
31
+ end
32
+ end
33
+
34
+ def to_mega(val, prefix)
35
+ case prefix
36
+ when :B then val.fdiv(MEGA)
37
+ when :KB then val.fdiv(KILO)
38
+ when :MB then val
39
+ when :GB then val * KILO
40
+ when :TB then val * MEGA
41
+ else unsupported_unit!(prefix)
42
+ end
43
+ end
44
+
45
+ def to_kilo(val, prefix)
46
+ case prefix
47
+ when :B then val.fdiv(KILO)
48
+ when :KB then val
49
+ when :MB then val * KILO
50
+ when :GB then val * MEGA
51
+ when :TB then val * GIGA
52
+ else unsupported_unit!(prefix)
53
+ end
54
+ end
55
+
56
+ def to_decimal_bi(val, prefix)
57
+ case prefix
58
+ when :B then val
59
+ when :KB then val * KILO
60
+ when :MB then val * MEGA
61
+ when :GB then val * GIGA
62
+ when :TB then val * TERA
63
+ else unsupported_unit!(prefix)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,18 @@
1
+ require 'active_support/core_ext/numeric/bytes'
2
+ require_relative 'size/bit'
3
+ require_relative 'size/cdn_speed'
4
+ require_relative 'size/frequency'
5
+ require_relative 'size/byte'
6
+ require_relative 'size/percentage'
7
+
8
+ module UsefulUtilities
9
+ module Size
10
+ include UsefulUtilities::Size::Bit
11
+ include UsefulUtilities::Size::CdnSpeed
12
+ include UsefulUtilities::Size::Frequency
13
+ include UsefulUtilities::Size::Byte
14
+ include UsefulUtilities::Size::Percentage
15
+
16
+ extend self
17
+ end
18
+ end
@@ -0,0 +1,97 @@
1
+ require 'active_support/all'
2
+
3
+ module UsefulUtilities
4
+ module Time
5
+ extend self
6
+
7
+ SECONDS_IN_HOUR = 3_600
8
+ MILLISECONDS_IN_SECOND = 1_000
9
+
10
+ # Whatever time is passed it will return it without any GMT offset and the passed time will be in UTC
11
+ # t = Time.now #=> 2013-12-19 14:01:22 +0200
12
+ # UsefulUtilities::Time.assume_utc(t) #=> 2013-12-19 14:01:22 UTC
13
+ def assume_utc(time)
14
+ time.to_datetime.change(offset: 0)
15
+ end
16
+
17
+ # Examples of usage:
18
+ # 2014-01-04 14:29:59 #=> 2014-01-04 14:00:00
19
+ # 2014-01-04 14:30:00 #=> 2014-01-04 15:00:00
20
+ def round_to_hours(time)
21
+ (time.min < 30) ? time.beginning_of_hour : time.end_of_hour
22
+ end
23
+
24
+ def beginning_of_next_hour(time)
25
+ time.beginning_of_hour.in(1.hour)
26
+ end
27
+
28
+ def beginning_of_next_day(time)
29
+ time.beginning_of_day.in(1.day)
30
+ end
31
+
32
+ def beginning_of_next_month(time)
33
+ time.beginning_of_month.in(1.month)
34
+ end
35
+
36
+ # yields local time of the beginning of each hour
37
+ # between start time & current time
38
+ def each_hour_from(from, till = ::Time.now)
39
+ cursor = from.dup.utc.beginning_of_hour
40
+ end_time = till.dup.utc.beginning_of_hour
41
+
42
+ while cursor < end_time
43
+ yield cursor, next_hour = beginning_of_next_hour(cursor)
44
+
45
+ cursor = next_hour
46
+ end
47
+ end
48
+
49
+ def each_day_from(from, till = ::Time.now)
50
+ cursor = from.beginning_of_day
51
+ end_time = till.beginning_of_day
52
+
53
+ while cursor < end_time
54
+ yield cursor, next_day = beginning_of_next_day(cursor)
55
+
56
+ cursor = next_day
57
+ end
58
+ end
59
+
60
+ # Parse and convert Time to the given time zone. If time zone is
61
+ # not given, Time is assumed to be given in UTC. Returns result in
62
+ # UTC
63
+ def to_utc(time_string, time_zone)
64
+ time = ::DateTime.parse(time_string) # Wed, 22 Aug 2012 13:34:18 +0000
65
+ rescue
66
+ nil
67
+ else
68
+ if time_zone.present?
69
+ current_user_offset = ::Time.now.in_time_zone(::Time.find_zone(time_zone)).strftime("%z") # "+0300"
70
+ time = time.change(:offset => current_user_offset) # Wed, 22 Aug 2012 13:34:18 +0300
71
+ time.utc # Wed, 22 Aug 2012 10:34:18 +0000
72
+ else
73
+ time
74
+ end
75
+ end
76
+
77
+ def to_milliseconds(time)
78
+ time.to_time.to_i * MILLISECONDS_IN_SECOND
79
+ end
80
+
81
+ # takes two objects: Time
82
+ def diff_in_hours(end_time, start_time)
83
+ ((end_time.to_i - start_time.to_i) / SECONDS_IN_HOUR).abs
84
+ end
85
+
86
+ def valid_date?(date)
87
+ return true if date.acts_like?(:date)
88
+ return false if date.blank?
89
+
90
+ # http://stackoverflow.com/a/35502357/717336
91
+ date_hash = Date._parse(date.to_s)
92
+ Date.valid_date?(date_hash[:year].to_i,
93
+ date_hash[:mon].to_i,
94
+ date_hash[:mday].to_i)
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,3 @@
1
+ module UsefulUtilities
2
+ VERSION = '5.4.5'.freeze
3
+ end
@@ -0,0 +1,17 @@
1
+ # It was used in outdated rake task, but we decided to leave for the future
2
+ module UsefulUtilities
3
+ module YAML
4
+ extend self
5
+
6
+ def rename_keys(file_path, key_map)
7
+ yaml_hash = ::YAML.load_file(file_path)
8
+ keys_to_rename = yaml_hash.keys & key_map.keys
9
+
10
+ return if keys_to_rename.empty?
11
+
12
+ keys_to_rename.each { |old_key| yaml_hash[key_map.fetch(old_key)] = yaml_hash.delete(old_key) }
13
+
14
+ File.open(file_path, 'w') { |file| ::YAML.dump(yaml_hash, file) }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ require 'active_support'
2
+
3
+ module UsefulUtilities
4
+ require_relative 'useful_utilities/version'
5
+ require_relative 'useful_utilities/ar' if defined?(ActiveRecord)
6
+ require_relative 'useful_utilities/numeric'
7
+ require_relative 'useful_utilities/time'
8
+ require_relative 'useful_utilities/size'
9
+ require_relative 'useful_utilities/api'
10
+ require_relative 'useful_utilities/i18n'
11
+ require_relative 'useful_utilities/hash'
12
+ require_relative 'useful_utilities/yaml'
13
+ require_relative 'useful_utilities/redhat_release'
14
+ require_relative 'useful_utilities/centos_version'
15
+ end
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: useful_utilities
3
+ version: !ruby/object:Gem::Version
4
+ version: 5.4.5
5
+ platform: ruby
6
+ authors:
7
+ - OnApp Ltd.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-02-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: timecop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: factory_girl_rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-its
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: |2
98
+ A bunch of useful modules to work with time/size constants/hashes
99
+ email: onapp@onapp.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - README.md
105
+ - Rakefile
106
+ - lib/useful_utilities.rb
107
+ - lib/useful_utilities/api.rb
108
+ - lib/useful_utilities/ar.rb
109
+ - lib/useful_utilities/centos_version.rb
110
+ - lib/useful_utilities/hash.rb
111
+ - lib/useful_utilities/i18n.rb
112
+ - lib/useful_utilities/numeric.rb
113
+ - lib/useful_utilities/redhat_release.rb
114
+ - lib/useful_utilities/size.rb
115
+ - lib/useful_utilities/size/bit.rb
116
+ - lib/useful_utilities/size/byte.rb
117
+ - lib/useful_utilities/size/cdn_speed.rb
118
+ - lib/useful_utilities/size/frequency.rb
119
+ - lib/useful_utilities/size/percentage.rb
120
+ - lib/useful_utilities/size/standard/binary.rb
121
+ - lib/useful_utilities/size/standard/decimal.rb
122
+ - lib/useful_utilities/time.rb
123
+ - lib/useful_utilities/version.rb
124
+ - lib/useful_utilities/yaml.rb
125
+ homepage: https://github.com/OnApp/useful_utilities
126
+ licenses:
127
+ - Apache 2.0
128
+ metadata: {}
129
+ post_install_message:
130
+ rdoc_options: []
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: 2.1.0
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ requirements: []
144
+ rubyforge_project:
145
+ rubygems_version: 2.4.3
146
+ signing_key:
147
+ specification_version: 4
148
+ summary: Helpful methods for time, sizes, hashes etc.
149
+ test_files: []