ruby-rails-extensions 1.0.0 → 1.1.0.pre.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -0
  3. data/lib/ruby-rails-extensions/errors.rb +17 -0
  4. data/lib/ruby-rails-extensions/extensions/all_keys.rb +10 -0
  5. data/lib/ruby-rails-extensions/extensions/all_values.rb +10 -0
  6. data/lib/ruby-rails-extensions/extensions/any_key.rb +10 -0
  7. data/lib/ruby-rails-extensions/extensions/any_value.rb +10 -0
  8. data/lib/ruby-rails-extensions/extensions/assign_nil.rb +67 -0
  9. data/lib/ruby-rails-extensions/extensions/boolean_scope.rb +49 -0
  10. data/lib/ruby-rails-extensions/extensions/clean_string.rb +41 -0
  11. data/lib/ruby-rails-extensions/extensions/compact_blank_join.rb +13 -0
  12. data/lib/ruby-rails-extensions/extensions/find_bang.rb +1 -10
  13. data/lib/ruby-rails-extensions/extensions/humanize_symbol.rb +11 -0
  14. data/lib/ruby-rails-extensions/extensions/no_keys.rb +10 -0
  15. data/lib/ruby-rails-extensions/extensions/no_values.rb +10 -0
  16. data/lib/ruby-rails-extensions/extensions/only_some.rb +28 -0
  17. data/lib/ruby-rails-extensions/extensions/presence_bang.rb +1 -10
  18. data/lib/ruby-rails-extensions/extensions/quarter_dates.rb +47 -0
  19. data/lib/ruby-rails-extensions/extensions/range_add.rb +47 -0
  20. data/lib/ruby-rails-extensions/extensions/range_multiply.rb +47 -0
  21. data/lib/ruby-rails-extensions/extensions/safe_parse.rb +42 -0
  22. data/lib/ruby-rails-extensions/extensions/select_present.rb +11 -0
  23. data/lib/ruby-rails-extensions/extensions/select_present_join.rb +7 -0
  24. data/lib/ruby-rails-extensions/extensions/set_to_sentence.rb +11 -0
  25. data/lib/ruby-rails-extensions/extensions/to_local.rb +26 -0
  26. data/lib/ruby-rails-extensions/extensions/to_negative_i.rb +45 -0
  27. data/lib/ruby-rails-extensions/extensions/to_nonzero_i.rb +45 -0
  28. data/lib/ruby-rails-extensions/extensions/to_positive_i.rb +45 -0
  29. data/lib/ruby-rails-extensions/extensions/todays_date.rb +17 -0
  30. data/lib/ruby-rails-extensions/extensions/uniq_map.rb +25 -0
  31. data/lib/ruby-rails-extensions/extensions/weighted_sum.rb +25 -0
  32. data/lib/ruby-rails-extensions/extensions/zero_range.rb +22 -0
  33. data/lib/ruby-rails-extensions/version.rb +1 -1
  34. data/lib/ruby-rails-extensions.rb +85 -47
  35. metadata +32 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a55953d9663b4130bb753fbab8f05304502281cc563cdc18e403c57287d82c7
4
- data.tar.gz: 558db93b9dfc5127d9277ddd7bf3bdb6f9e5aad00533e3cdc7e06030ec09fb0b
3
+ metadata.gz: 8bfe888c5a0bc6a8542e1836c8e96b6660285263169a1982ebf7fc93bc837a21
4
+ data.tar.gz: 651208392b2a60e9b36a9b845c1937c5a75a99bbf05872b68dc44fa2a49b0bbf
5
5
  SHA512:
6
- metadata.gz: 2b0dfe8345bdba53714391d792efbe466eacb34ba98660ac25920e69a592598f43df050de97ffe55edc77f8c5b04dca87efcf3e7d7ac321a3f64f0f003350afb
7
- data.tar.gz: 7f33c483db30016489856be7989079742faaebbbd18c5b949d22393dde78538c4e9e71afc73d7b2f4ae71446256c19ca69f9a5aa0a3ad5bd4c9a79ebeb5157d1
6
+ metadata.gz: a3a3ed90725bd9a2abb39d3d6cabb17b427082af51e923c668226176c9467b06695f735417243b651777dc363dc5c517b5a86b83287b5f1405df89ed5d05565b
7
+ data.tar.gz: ee96065885e04d3afa8d1ce6a293142edd672f6588993f0a8f793cf24a08b20888aa803ea962e14c5d75a22fb39286610042153191a893cb8301c4bde189b097
data/CHANGELOG.md CHANGED
@@ -1,6 +1,40 @@
1
1
  Unreleased Changes
2
2
  ------------------
3
3
 
4
+ 1.1.0 (2023-09-27)
5
+ ------------------
6
+
7
+ * Modules added:
8
+ * `safe_parse`
9
+ * `to_local`
10
+ * `assign_nil`
11
+ * `todays_date`
12
+ * `humanize_symbol`
13
+ * `weighted_sum`
14
+ * `any_value`
15
+ * `all_values`
16
+ * `no_values`
17
+ * `any_key`
18
+ * `all_keys`
19
+ * `no_keys`
20
+ * `set_to_sentence`
21
+ * `uniq_map`
22
+ * `only_some`
23
+ * `clean_string`
24
+ * `select_present`
25
+ * `quarter_dates`
26
+ * `compact_blank_join`
27
+ * `select_present_join`
28
+ * `range_add`
29
+ * `range_multiply`
30
+ * `zero_range`
31
+ * `boolean_scope`
32
+ * `to_positive_i`
33
+ * `to_negative_i`
34
+ * `to_nonzero_i`
35
+ * Other changes:
36
+ * Restructured errors' namespace
37
+
4
38
  1.0.0 (2023-09-25)
5
39
  ------------------
6
40
 
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyRailsExtensions
4
+ module Errors
5
+ class NonNumericError < StandardError
6
+ end
7
+
8
+ class NotFoundError < StandardError
9
+ end
10
+
11
+ class BlankObjectError < StandardError
12
+ end
13
+
14
+ class InvalidFormatError < StandardError
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ Hash.class_eval do
4
+ unless method_defined?(:all_keys?)
5
+ # @see Enumerable#all?
6
+ def all_keys?(...)
7
+ keys.all?(...)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ Hash.class_eval do
4
+ unless method_defined?(:all_values?)
5
+ # @see Enumerable#all?
6
+ def all_values?(...)
7
+ values.all?(...)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ Hash.class_eval do
4
+ unless method_defined?(:any_key?)
5
+ # @see Enumerable#any?
6
+ def any_key?(...)
7
+ keys.any?(...)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ Hash.class_eval do
4
+ unless method_defined?(:any_value?)
5
+ # @see Enumerable#any?
6
+ def any_value?(...)
7
+ values.any?(...)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ if defined?(ActiveModel::AttributeAssignment) && Hash.method_defined?(:stringify_keys)
4
+ module ActiveModel
5
+ module AttributeAssignment
6
+ unless method_defined?(:assign_nil_attributes)
7
+ # Allows you to set nil attributes by passing in a hash of attributes with
8
+ # keys matching the attribute names.
9
+ #
10
+ # @raise [ActiveModel::ForbiddenAttributesError] If the passed hash responds to `permitted?` method
11
+ # and the return value of this method is +false+.
12
+ #
13
+ # @example
14
+ #
15
+ # class Cat
16
+ # include ActiveModel::AttributeAssignment
17
+ # attr_accessor :name, :status
18
+ # end
19
+ #
20
+ # cat = Cat.new
21
+ # cat.assign_nil_attributes(name: "Gorby")
22
+ # cat.name # => 'Gorby'
23
+ # cat.status # => nil
24
+ # cat.assign_nil_attributes(status: "yawning")
25
+ # cat.name # => 'Gorby'
26
+ # cat.status # => 'yawning'
27
+ # cat.assign_nil_attributes(status: "sleeping")
28
+ # cat.name # => 'Gorby'
29
+ # cat.status # => 'yawning'
30
+ #
31
+ # @param new_attributes
32
+ #
33
+ # @return [void]
34
+ #
35
+ def assign_nil_attributes(new_attributes)
36
+ unless new_attributes.respond_to?(:stringify_keys)
37
+ raise(ArgumentError, 'When assigning attributes, you must pass a hash as an argument.')
38
+ end
39
+
40
+ return if new_attributes.empty?
41
+
42
+ attributes = new_attributes.stringify_keys
43
+
44
+ _assign_nil_attributes(sanitize_for_mass_assignment(attributes))
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ unless private_method_defined?(:_assign_nil_attributes)
51
+ # Assign any `nil` attribute
52
+ #
53
+ # @param attributes [Hash]
54
+ #
55
+ # @return [void]
56
+ #
57
+ def _assign_nil_attributes(attributes)
58
+ attributes.each do |k, v|
59
+ next unless v.nil?
60
+
61
+ _assign_attribute(k, v)
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyRailsExtensions
4
+ module Extensions
5
+ module BooleanScope
6
+ if defined?(ActiveSupport::Concern)
7
+ extend ActiveSupport::Concern
8
+
9
+ class_methods do
10
+ # Calls `boolean_scope` for each boolean column
11
+ def add_boolean_scopes
12
+ return unless table_exists?
13
+
14
+ columns.each do |column|
15
+ next unless column.type == :boolean
16
+
17
+ # @!method not_#{column.name}?
18
+ # @return [Boolean]
19
+ # @!method column.name
20
+ # @!scope class
21
+ # @return [ActiveRecord::Relation<>]
22
+ # @!method not_#{column.name}
23
+ # @!scope class
24
+ # @return [ActiveRecord::Relation<>]
25
+ boolean_scope(column.name)
26
+ end
27
+ end
28
+
29
+ # Defines 2 scopes and 1 ? method
30
+ #
31
+ # @param column_name [Symbol, String] The boolean column name
32
+ # @param negative [Symbol, String] opposite of the column name
33
+ # defaults to the column name with "not_" as a prefix
34
+ #
35
+ # @return [void]
36
+ #
37
+ def boolean_scope(column_name, negative = "not_#{column_name}")
38
+ scope(:"#{column_name}", -> { where(column_name => true) })
39
+ scope(:"#{negative}", -> { where(column_name => false) })
40
+
41
+ define_method("#{negative}?") do
42
+ !__send__("#{column_name}?")
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ String.class_eval do
4
+ unless method_defined?(:clean!)
5
+ # Remove all non-UTF-8 chars from a string.
6
+ #
7
+ # @param replace_with [String, nil] What to replace invalid chars with.
8
+ #
9
+ # @return [String]
10
+ #
11
+ def clean!(replace_with = '')
12
+ replace(encode('UTF-8', invalid: :replace, undef: :replace, replace: replace_with))
13
+ end
14
+ end
15
+
16
+ unless method_defined?(:clean)
17
+ # @see {#clean!}
18
+ def clean(replace_with = '')
19
+ dup.clean!(replace_with)
20
+ end
21
+ end
22
+
23
+ unless method_defined?(:clean_binary!)
24
+ # Remove all non-UTF-8 chars from a string and convert to binary.
25
+ #
26
+ # @param replace_with [String, nil] What to replace invalid chars with.
27
+ #
28
+ # @return [String]
29
+ #
30
+ def clean_binary!(replace_with = '')
31
+ replace(encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: replace_with))
32
+ end
33
+ end
34
+
35
+ unless method_defined?(:clean_binary)
36
+ # @see {#clean_binary!}
37
+ def clean_binary(replace_with = '')
38
+ dup.clean_binary!(replace_with)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ Enumerable.class_eval do
4
+ if method_defined?(:compact_blank) && !method_defined?(:compact_blank_join)
5
+ # Joins the elements together after calling `compact_blank`
6
+ #
7
+ # @return [String]
8
+ #
9
+ def compact_blank_join(using = '')
10
+ compact_blank.join(using)
11
+ end
12
+ end
13
+ end
@@ -3,21 +3,12 @@
3
3
  require 'forwardable'
4
4
  require 'set'
5
5
 
6
- module RubyRailsExtensions
7
- module Extensions
8
- module FindBang
9
- class NotFoundError < StandardError
10
- end
11
- end
12
- end
13
- end
14
-
15
6
  Array.class_eval do
16
7
  unless method_defined?(:find!)
17
8
  # :nodoc:
18
9
  def find!(&block)
19
10
  x = find(&block)
20
- raise(RubyRailsExtensions::Extensions::FindBang::NotFoundError, 'Not found') if x.nil?
11
+ raise(RubyRailsExtensions::Errors::NotFoundError, 'Not found') if x.nil?
21
12
 
22
13
  x
23
14
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ Symbol.class_eval do
6
+ unless method_defined?(:humanize)
7
+ extend Forwardable
8
+
9
+ def_delegators :to_s, :humanize
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ Hash.class_eval do
4
+ unless method_defined?(:no_keys?)
5
+ # @see Enumerable#none?
6
+ def no_keys?(...)
7
+ keys.none?(...)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ Hash.class_eval do
4
+ unless method_defined?(:no_values?)
5
+ # @see Enumerable#none?
6
+ def no_values?(...)
7
+ values.none?(...)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ Array.class_eval do
4
+ unless method_defined?(:only_some?)
5
+ # Same as `my_array.any?(&block) && !my_array.all?(&block)`
6
+ #
7
+ # @return [Boolean]
8
+ #
9
+ def only_some?(*meth_args)
10
+ # Check arg size since `any?` arg take presence over block
11
+ return any?(*meth_args) && !all?(*meth_args) if meth_args.size.positive?
12
+
13
+ any = false
14
+ all = true
15
+
16
+ each do |*args|
17
+ result = yield(*args)
18
+
19
+ any ||= result
20
+ all &&= result
21
+
22
+ break if any && !all
23
+ end
24
+
25
+ return any && !all
26
+ end
27
+ end
28
+ end
@@ -1,14 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RubyRailsExtensions
4
- module Extensions
5
- module PresenceBang
6
- class BlankObjectError < StandardError
7
- end
8
- end
9
- end
10
- end
11
-
12
3
  Object.class_eval do
13
4
  unless method_defined?(:presence!)
14
5
  # Returns self if `present?`
@@ -18,7 +9,7 @@ Object.class_eval do
18
9
  # @return [*]
19
10
  #
20
11
  def presence!
21
- raise(RubyRailsExtensions::Extensions::PresenceBang::BlankObjectError, 'Blank object') if blank?
12
+ raise(RubyRailsExtensions::Errors::BlankObjectError, 'Blank object') if blank?
22
13
 
23
14
  self
24
15
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ String.class_eval do
4
+ if !method_defined?(:quarter_start) && Date.instance_methods.include?(:beginning_of_quarter)
5
+ # Return the quarter start date.
6
+ #
7
+ # @return [Date]
8
+ #
9
+ def quarter_start
10
+ quarter_date.beginning_of_quarter
11
+ end
12
+ end
13
+
14
+ if !method_defined?(:quarter_end) && Date.instance_methods.include?(:end_of_quarter)
15
+ # Return the quarter end date.
16
+ #
17
+ # @return [Date]
18
+ #
19
+ def quarter_end
20
+ quarter_date.end_of_quarter
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ unless private_method_defined?(:quarter_date)
27
+ # Parses a string for a quarter date. Expects the string to follow: 'qQyy' where
28
+ # q = 1/2/3/4 and yy to be the last two digits of the year.
29
+ #
30
+ # @raise [RubyRailsExtensions::Errors::InvalidFormatError] if `self` is not qQyy
31
+ #
32
+ # @return [Date]
33
+ #
34
+ def quarter_date
35
+ unless match?(/\A[1-4]q\d\d\z/i)
36
+ raise(RubyRailsExtensions::Errors::InvalidFormatError, "Unexpected format (given #{self}, expected qQyy)")
37
+ end
38
+
39
+ values = scan(/\d/)
40
+ quarter = values.shift.to_i
41
+ year = "20#{values.join('')}".to_i
42
+ month = quarter * 3
43
+
44
+ Date.new(year, month, 1)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ Range.class_eval do
4
+ unless method_defined?(:+)
5
+ # Allows adding a to a range. This will create a new range since ranges are immutable.
6
+ #
7
+ # @note Make sure to assign this to a new var or inline replacement `+=`.
8
+ #
9
+ # @raise [RubyRailsExtensions::Errors::NonNumericError]
10
+ #
11
+ # @param other [Numeric, Range<Numeric>]
12
+ #
13
+ # @return [Range]
14
+ #
15
+ def +(other)
16
+ unless self.begin.is_a?(Numeric)
17
+ raise(
18
+ RubyRailsExtensions::Errors::NonNumericError,
19
+ "Wrong range type (given #{self.begin.class}, expected Numeric)"
20
+ )
21
+ end
22
+
23
+ new_begin, new_end =
24
+ if other.is_a?(Range)
25
+ unless other.begin.is_a?(Numeric)
26
+ raise(
27
+ RubyRailsExtensions::Errors::NonNumericError,
28
+ "Wrong range type (given #{other.begin.class}, expected Numeric)"
29
+ )
30
+ end
31
+
32
+ [self.begin + other.begin, self.end + other.end]
33
+ else
34
+ unless other.is_a?(Numeric)
35
+ raise(
36
+ RubyRailsExtensions::Errors::NonNumericError,
37
+ "Wrong type (given #{other.class}, expected Numeric)"
38
+ )
39
+ end
40
+
41
+ [self.begin + other, self.end + other]
42
+ end
43
+
44
+ Range.new(new_begin, new_end, exclude_end?)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ Range.class_eval do
4
+ unless method_defined?(:*)
5
+ # Allows multiplying a range. This will create a new range due to range objects being immutable.
6
+ #
7
+ # @note Make sure to assign this to a new var or do inline replacement `*=`.
8
+ #
9
+ # @raise [RubyRailsExtensions::Errors::NonNumericError]
10
+ #
11
+ # @param other [Numeric, Range<Numeric>]
12
+ #
13
+ # @return [Range]
14
+ #
15
+ def *(other)
16
+ unless self.begin.is_a?(Numeric)
17
+ raise(
18
+ RubyRailsExtensions::Errors::NonNumericError,
19
+ "Wrong range type (given #{self.begin.class}, expected Numeric)"
20
+ )
21
+ end
22
+
23
+ new_begin, new_end =
24
+ if other.is_a?(Range)
25
+ unless other.begin.is_a?(Numeric)
26
+ raise(
27
+ RubyRailsExtensions::Errors::NonNumericError,
28
+ "Wrong range type (given #{other.begin.class}, expected Numeric)"
29
+ )
30
+ end
31
+
32
+ [self.begin * other.begin, self.end * other.end]
33
+ else
34
+ unless other.is_a?(Numeric)
35
+ raise(
36
+ RubyRailsExtensions::Errors::NonNumericError,
37
+ "Wrong type (given #{other.class}, expected Numeric)"
38
+ )
39
+ end
40
+
41
+ [self.begin * other, self.end * other]
42
+ end
43
+
44
+ Range.new(new_begin, new_end, exclude_end?)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ Date.class_eval do
4
+ class << self
5
+ unless method_defined?(:safe_parse)
6
+ # Parses the `str` and returns `nil` if invalid
7
+ def safe_parse(str)
8
+ parse(str)
9
+ rescue
10
+ nil
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ Time.class_eval do
17
+ class << self
18
+ unless method_defined?(:safe_parse)
19
+ # Parses the `str` and returns `nil` if invalid
20
+ def safe_parse(str)
21
+ parse(str)
22
+ rescue
23
+ nil
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ if defined?(ActiveSupport::TimeZone)
30
+ ActiveSupport::TimeZone.class_eval do
31
+ class << self
32
+ unless method_defined?(:safe_parse)
33
+ # Parses the `str` and returns `nil` if invalid
34
+ def safe_parse(str)
35
+ parse(str)
36
+ rescue
37
+ nil
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ Enumerable.class_eval do
4
+ if method_defined?(:compact_blank) && !method_defined?(:select_present)
5
+ alias_method :select_present, :compact_blank
6
+ end
7
+
8
+ if method_defined?(:compact_blank!) && !method_defined?(:select_present!)
9
+ alias_method :select_present!, :compact_blank!
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ Enumerable.class_eval do
4
+ if method_defined?(:compact_blank_join) && !method_defined?(:select_present_join)
5
+ alias_method :select_present_join, :compact_blank_join
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ Set.class_eval do
6
+ unless method_defined?(:to_sentence)
7
+ extend Forwardable
8
+
9
+ def_delegators :to_a, :to_sentence
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TimeWithZone defines `in_time_zone`
4
+ if defined?(ActiveSupport::TimeWithZone)
5
+ require 'forwardable'
6
+
7
+ Time.class_eval do
8
+ unless method_defined?(:to_local)
9
+ extend Forwardable
10
+
11
+ def_delegators :to_datetime, :to_local
12
+ end
13
+ end
14
+
15
+ DateTime.class_eval do
16
+ unless method_defined?(:to_local)
17
+ # Converts to an Eastern time zone
18
+ #
19
+ # @return [DateTime]
20
+ #
21
+ def to_local
22
+ in_time_zone(RubyRailsExtensions.configuration.default_time_zone || 'Eastern Time (US & Canada)').to_datetime
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ String.class_eval do
4
+ unless method_defined?(:to_negative_i)
5
+ # Calls `to_i` and returns the value if it is negative
6
+ #
7
+ # @return [Integer, Nil]
8
+ #
9
+ def to_negative_i
10
+ val = to_i
11
+
12
+ return unless val.negative?
13
+
14
+ val
15
+ end
16
+ end
17
+ end
18
+
19
+ Numeric.class_eval do
20
+ unless method_defined?(:to_negative_i)
21
+ # Calls `to_i` and returns the value if it is negative
22
+ #
23
+ # @return [Integer, Nil]
24
+ #
25
+ def to_negative_i
26
+ val = to_i
27
+
28
+ return unless val.negative?
29
+
30
+ val
31
+ end
32
+ end
33
+ end
34
+
35
+ NilClass.class_eval do
36
+ unless method_defined?(:to_negative_i)
37
+ # Calls `to_i` and returns the value if it is negative
38
+ #
39
+ # @return [Nil]
40
+ #
41
+ def to_negative_i
42
+ nil
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ String.class_eval do
4
+ unless method_defined?(:to_nonzero_i)
5
+ # Calls `to_i` and returns the value if it is nonzero
6
+ #
7
+ # @return [Integer, Nil]
8
+ #
9
+ def to_nonzero_i
10
+ val = to_i
11
+
12
+ return if val.zero?
13
+
14
+ val
15
+ end
16
+ end
17
+ end
18
+
19
+ Numeric.class_eval do
20
+ unless method_defined?(:to_nonzero_i)
21
+ # Calls `to_i` and returns the value if it is nonzero
22
+ #
23
+ # @return [Integer, Nil]
24
+ #
25
+ def to_nonzero_i
26
+ val = to_i
27
+
28
+ return if val.zero?
29
+
30
+ val
31
+ end
32
+ end
33
+ end
34
+
35
+ NilClass.class_eval do
36
+ unless method_defined?(:to_nonzero_i)
37
+ # Calls `to_i` and returns the value if it is nonzero
38
+ #
39
+ # @return [Integer, Nil]
40
+ #
41
+ def to_nonzero_i
42
+ nil
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ String.class_eval do
4
+ unless method_defined?(:to_positive_i)
5
+ # Calls `to_i` and returns the value if it is positive
6
+ #
7
+ # @return [Integer, Nil]
8
+ #
9
+ def to_positive_i
10
+ val = to_i
11
+
12
+ return unless val.positive?
13
+
14
+ val
15
+ end
16
+ end
17
+ end
18
+
19
+ Numeric.class_eval do
20
+ unless method_defined?(:to_positive_i)
21
+ # Calls `to_i` and returns the value if it is positive
22
+ #
23
+ # @return [Integer, Nil]
24
+ #
25
+ def to_positive_i
26
+ val = to_i
27
+
28
+ return unless val.positive?
29
+
30
+ val
31
+ end
32
+ end
33
+ end
34
+
35
+ NilClass.class_eval do
36
+ unless method_defined?(:to_positive_i)
37
+ # Calls `to_i` and returns the value if it is positive
38
+ #
39
+ # @return [Integer, Nil]
40
+ #
41
+ def to_positive_i
42
+ nil
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ if defined?(ActiveSupport::TimeWithZone) && Time.method_defined?(:to_local)
4
+ Date.class_eval do
5
+ class << self
6
+ unless method_defined?(:todays_date)
7
+ # Returns today according to Eastern time
8
+ #
9
+ # @return [Date]
10
+ #
11
+ def todays_date
12
+ Time.zone.now.to_local.to_date
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ Array.class_eval do
4
+ unless method_defined?(:uniq_map)
5
+ # Same as `my_array.map(&block).uniq`
6
+ #
7
+ # @return [Array, Enumerable]
8
+ #
9
+ def uniq_map
10
+ return to_enum(:uniq_map) unless block_given?
11
+
12
+ results = []
13
+
14
+ each do |*args|
15
+ result = yield(*args)
16
+
17
+ next if results.include?(result)
18
+
19
+ results.push(result)
20
+ end
21
+
22
+ return results
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ Array.class_eval do
4
+ unless method_defined?(:weighted_sum)
5
+ # Sums the array with each element weighing 10 times as the next.
6
+ # Expects `self` to be [Array<Numeric>]
7
+ #
8
+ # @raise [RubyRailsExtensions::Errors::NonNumericError] if any element is not Numeric
9
+ #
10
+ # @return [Integer]
11
+ #
12
+ def weighted_sum
13
+ each_with_index.sum do |val, index|
14
+ unless Numeric === val
15
+ raise(
16
+ RubyRailsExtensions::Errors::NonNumericError,
17
+ "Wrong element type (given #{val.class}, expected Numeric)"
18
+ )
19
+ end
20
+
21
+ val * (10**(size - index))
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ Range.class_eval do
4
+ unless method_defined?(:zero?)
5
+ # Checks if the whole range is zero.
6
+ #
7
+ # @raise [RubyRailsExtensions::Errors::NonNumericError]
8
+ #
9
+ # @return [Boolean]
10
+ #
11
+ def zero?
12
+ unless self.begin.is_a?(Numeric)
13
+ raise(
14
+ RubyRailsExtensions::Errors::NonNumericError,
15
+ "Wrong range type (given #{self.begin.class}, expected Numeric)"
16
+ )
17
+ end
18
+
19
+ self.begin.zero? && self.end.zero?
20
+ end
21
+ end
22
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyRailsExtensions
4
- VERSION = '1.0.0'
4
+ VERSION = '1.1.0-rc.1'
5
5
  end
@@ -1,40 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RubyRailsExtensions
4
- # @return [CONFIGURATION]
5
- def self.configuration
6
- @configuration ||= CONFIGURATION.new
7
- end
8
-
9
- # @yield [Configuration]
10
- def self.configure
11
- yield(configuration)
12
-
13
- gem_list.each do |gem_base|
14
- next unless configuration.public_send("#{flag_name(gem_base)}?")
15
-
16
- require_relative("ruby-rails-extensions/extensions/#{gem_base}")
17
- end
18
- end
19
-
20
- # @return [Array<Symbol>]
21
- def configuration_flags
22
- CONFIGURATION.members
23
- end
24
-
25
- module_function :configuration_flags
26
-
27
- private
28
-
29
- # @return [Symbol] the flag name
30
- def flag_name(gem_base)
31
- :"include_#{gem_base}"
32
- end
33
-
34
- module_function :flag_name
3
+ require_relative 'ruby-rails-extensions/errors'
35
4
 
5
+ module RubyRailsExtensions
6
+ class Configuration
36
7
  BOOLEAN_GEMS = %i[
8
+ all_keys
9
+ all_values
10
+ any_key
11
+ any_value
12
+ assign_nil
13
+ boolean_scope
14
+ clean_string
37
15
  compact_map
16
+ compact_blank_join
38
17
  current_day
39
18
  current_month
40
19
  current_week
@@ -46,46 +25,105 @@ module RubyRailsExtensions
46
25
  first_dupe
47
26
  google_format
48
27
  hash_only
28
+ humanize_symbol
49
29
  in_utc
50
30
  input
51
31
  month_and_year
52
32
  month_year
33
+ no_keys
34
+ no_values
35
+ only_some
53
36
  overlaps
54
37
  pipe
55
38
  presence_bang
39
+ quarter_dates
40
+ range_add
41
+ range_multiply
56
42
  remove_reserved_keywords
43
+ safe_parse
44
+ select_present
45
+ select_present_join
46
+ set_to_sentence
57
47
  to_bool
58
48
  to_dec
59
49
  to_i
50
+ to_local
51
+ to_negative_i
52
+ to_nonzero_i
60
53
  to_or_sentence
54
+ to_positive_i
61
55
  to_sort_i
62
56
  to_x
57
+ todays_date
58
+ uniq_map
63
59
  usd_to_f
64
60
  usd_to_i
61
+ weighted_sum
65
62
  yesno
63
+ zero_range
66
64
  ].freeze
67
65
 
68
- # @return [Array<Symbol>] the list of gems
69
- def gem_list
70
- BOOLEAN_GEMS
66
+ attr_accessor :default_time_zone
67
+
68
+ # @return [Symbol] the flag name
69
+ def self.flag_name(gem_base)
70
+ :"include_#{gem_base}"
71
71
  end
72
72
 
73
- module_function :gem_list
73
+ BOOLEAN_GEMS.each do |extension_name|
74
+ include_extension = flag_name(extension_name)
74
75
 
75
- CONFIGURATION = Struct.new(*gem_list.map { |gem| flag_name(gem) }) do
76
- members.each do |gem_member|
77
- define_method(:"#{gem_member}?") do
78
- public_send(gem_member) != false
79
- end
76
+ attr_accessor include_extension
77
+
78
+ define_method(:"#{extension_name}?") do
79
+ public_send(include_extension) != false
80
80
  end
81
+ end
81
82
 
82
- # Sets all flags to true by default
83
- def initialize
84
- super
83
+ # Sets all flags to true by default
84
+ def initialize
85
+ super
85
86
 
86
- members.each do |gem_member|
87
- public_send("#{gem_member}=", true)
88
- end
87
+ BOOLEAN_GEMS.each do |extension_name|
88
+ include_extension = flag_name(extension_name)
89
+
90
+ public_send("#{include_extension}=", true)
89
91
  end
90
92
  end
93
+
94
+ # @return [Array<Symbol>]
95
+ def flags
96
+ BOOLEAN_GEMS.map { |f| flag_name(f) }
97
+ end
98
+
99
+ private
100
+
101
+ # @return [Symbol] the flag name
102
+ def flag_name(gem_base)
103
+ self.class.flag_name(gem_base)
104
+ end
105
+ end
106
+
107
+ # @return [Configuration]
108
+ def self.configuration
109
+ @configuration ||= Configuration.new
110
+ end
111
+
112
+ # @yield [Configuration]
113
+ def self.configure
114
+ yield(configuration)
115
+
116
+ Configuration::BOOLEAN_GEMS.each do |extension|
117
+ next unless configuration.public_send("#{extension}?")
118
+
119
+ require_relative("ruby-rails-extensions/extensions/#{extension}")
120
+ end
121
+ end
122
+
123
+ # @return [Array<Symbol>]
124
+ def configuration_flags
125
+ configuration.flags
126
+ end
127
+
128
+ module_function :configuration_flags
91
129
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-rails-extensions
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0.pre.rc.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brands Insurance
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-25 00:00:00.000000000 Z
11
+ date: 2023-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop-rubomatic-rails
@@ -40,6 +40,15 @@ files:
40
40
  - CHANGELOG.md
41
41
  - LICENSE.txt
42
42
  - lib/ruby-rails-extensions.rb
43
+ - lib/ruby-rails-extensions/errors.rb
44
+ - lib/ruby-rails-extensions/extensions/all_keys.rb
45
+ - lib/ruby-rails-extensions/extensions/all_values.rb
46
+ - lib/ruby-rails-extensions/extensions/any_key.rb
47
+ - lib/ruby-rails-extensions/extensions/any_value.rb
48
+ - lib/ruby-rails-extensions/extensions/assign_nil.rb
49
+ - lib/ruby-rails-extensions/extensions/boolean_scope.rb
50
+ - lib/ruby-rails-extensions/extensions/clean_string.rb
51
+ - lib/ruby-rails-extensions/extensions/compact_blank_join.rb
43
52
  - lib/ruby-rails-extensions/extensions/compact_map.rb
44
53
  - lib/ruby-rails-extensions/extensions/current_day.rb
45
54
  - lib/ruby-rails-extensions/extensions/current_month.rb
@@ -52,23 +61,42 @@ files:
52
61
  - lib/ruby-rails-extensions/extensions/first_dupe.rb
53
62
  - lib/ruby-rails-extensions/extensions/google_format.rb
54
63
  - lib/ruby-rails-extensions/extensions/hash_only.rb
64
+ - lib/ruby-rails-extensions/extensions/humanize_symbol.rb
55
65
  - lib/ruby-rails-extensions/extensions/in_utc.rb
56
66
  - lib/ruby-rails-extensions/extensions/input.rb
57
67
  - lib/ruby-rails-extensions/extensions/month_and_year.rb
58
68
  - lib/ruby-rails-extensions/extensions/month_year.rb
69
+ - lib/ruby-rails-extensions/extensions/no_keys.rb
70
+ - lib/ruby-rails-extensions/extensions/no_values.rb
71
+ - lib/ruby-rails-extensions/extensions/only_some.rb
59
72
  - lib/ruby-rails-extensions/extensions/overlaps.rb
60
73
  - lib/ruby-rails-extensions/extensions/pipe.rb
61
74
  - lib/ruby-rails-extensions/extensions/presence_bang.rb
75
+ - lib/ruby-rails-extensions/extensions/quarter_dates.rb
76
+ - lib/ruby-rails-extensions/extensions/range_add.rb
77
+ - lib/ruby-rails-extensions/extensions/range_multiply.rb
62
78
  - lib/ruby-rails-extensions/extensions/remove_reserved_keywords.rb
79
+ - lib/ruby-rails-extensions/extensions/safe_parse.rb
80
+ - lib/ruby-rails-extensions/extensions/select_present.rb
81
+ - lib/ruby-rails-extensions/extensions/select_present_join.rb
82
+ - lib/ruby-rails-extensions/extensions/set_to_sentence.rb
63
83
  - lib/ruby-rails-extensions/extensions/to_bool.rb
64
84
  - lib/ruby-rails-extensions/extensions/to_dec.rb
65
85
  - lib/ruby-rails-extensions/extensions/to_i.rb
86
+ - lib/ruby-rails-extensions/extensions/to_local.rb
87
+ - lib/ruby-rails-extensions/extensions/to_negative_i.rb
88
+ - lib/ruby-rails-extensions/extensions/to_nonzero_i.rb
66
89
  - lib/ruby-rails-extensions/extensions/to_or_sentence.rb
90
+ - lib/ruby-rails-extensions/extensions/to_positive_i.rb
67
91
  - lib/ruby-rails-extensions/extensions/to_sort_i.rb
68
92
  - lib/ruby-rails-extensions/extensions/to_x.rb
93
+ - lib/ruby-rails-extensions/extensions/todays_date.rb
94
+ - lib/ruby-rails-extensions/extensions/uniq_map.rb
69
95
  - lib/ruby-rails-extensions/extensions/usd_to_f.rb
70
96
  - lib/ruby-rails-extensions/extensions/usd_to_i.rb
97
+ - lib/ruby-rails-extensions/extensions/weighted_sum.rb
71
98
  - lib/ruby-rails-extensions/extensions/yesno.rb
99
+ - lib/ruby-rails-extensions/extensions/zero_range.rb
72
100
  - lib/ruby-rails-extensions/version.rb
73
101
  homepage: https://github.com/BrandsInsurance/rails-extensions
74
102
  licenses:
@@ -87,9 +115,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
87
115
  version: 3.0.1
88
116
  required_rubygems_version: !ruby/object:Gem::Requirement
89
117
  requirements:
90
- - - ">="
118
+ - - ">"
91
119
  - !ruby/object:Gem::Version
92
- version: '0'
120
+ version: 1.3.1
93
121
  requirements: []
94
122
  rubygems_version: 3.2.15
95
123
  signing_key: