useful_utilities 5.4.5

Sign up to get free protection for your applications and to get access to all the features.
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: []