ruby-rails-extensions 0.1.0 → 0.2.0.pre.rc.1

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.
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: d56af69b3c8476fe02a20b1b9afd927f80e8ac40ff659e5e6654ee590d7ce15e
4
- data.tar.gz: 1ce72548d0d1d98c1c77b45c7cf417858bd1b0388a3fd71e6468b00a9c9e8c88
3
+ metadata.gz: 254dfe1a4780e64d77d83b9dc03da054f8142d289815defd5f6bc0b541502f0b
4
+ data.tar.gz: 18b978ce2b280bb6ac6e9c4904fe5ae489bbc357b7f1511cddc81e9c41ec7b52
5
5
  SHA512:
6
- metadata.gz: '08c4e8c6951e77ebdf318385fcf6d9e490260786e297455e7b5dfc804672659234aba622eeab15d864cb261f1744e9d15bb3ec184e11f4b4ac3694f2cc14fda1'
7
- data.tar.gz: bba958f49013cca6f9fcee9bbada3f31c9f8b9a36577aeec19751d393a71e0e857332fe851403f5b0dc189170896d125de4eb6ccd0855d111909adf14c8d262e
6
+ metadata.gz: ca2e677dbd1bdc740bbd615ff7fb5279182a779790c03681ca019e55a4cdfcc79c446dfa1b7dcf93cfcf5f850c3b6ca3f97cf40d1e31a74e5127f3c386e2cacb
7
+ data.tar.gz: b848d425417bba87de84d15421d8024ddf951d5e5012083a4f6420733c1203b2fbc27c5becf69596392daecd0aaef2917dbf8a8487653d2769813da9a5d1af2c
data/CHANGELOG.md CHANGED
@@ -1,6 +1,40 @@
1
1
  Unreleased Changes
2
2
  ------------------
3
3
 
4
+ 0.2.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
  0.1.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?(*args, &block)
7
+ keys.all?(*args, &block)
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?(*args,&block)
7
+ values.all?(*args,&block)
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?(*args,&block)
7
+ keys.any?(*args,&block)
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?(*args,&block)
7
+ values.any?(*args,&block)
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?(*args,&block)
7
+ keys.none?(*args,&block)
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?(*args,&block)
7
+ values.none?(*args,&block)
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 = '0.1.0'
4
+ VERSION = '0.2.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: 0.1.0
4
+ version: 0.2.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-26 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
@@ -48,6 +48,15 @@ files:
48
48
  - CHANGELOG.md
49
49
  - LICENSE.txt
50
50
  - lib/ruby-rails-extensions.rb
51
+ - lib/ruby-rails-extensions/errors.rb
52
+ - lib/ruby-rails-extensions/extensions/all_keys.rb
53
+ - lib/ruby-rails-extensions/extensions/all_values.rb
54
+ - lib/ruby-rails-extensions/extensions/any_key.rb
55
+ - lib/ruby-rails-extensions/extensions/any_value.rb
56
+ - lib/ruby-rails-extensions/extensions/assign_nil.rb
57
+ - lib/ruby-rails-extensions/extensions/boolean_scope.rb
58
+ - lib/ruby-rails-extensions/extensions/clean_string.rb
59
+ - lib/ruby-rails-extensions/extensions/compact_blank_join.rb
51
60
  - lib/ruby-rails-extensions/extensions/compact_map.rb
52
61
  - lib/ruby-rails-extensions/extensions/current_day.rb
53
62
  - lib/ruby-rails-extensions/extensions/current_month.rb
@@ -60,23 +69,42 @@ files:
60
69
  - lib/ruby-rails-extensions/extensions/first_dupe.rb
61
70
  - lib/ruby-rails-extensions/extensions/google_format.rb
62
71
  - lib/ruby-rails-extensions/extensions/hash_only.rb
72
+ - lib/ruby-rails-extensions/extensions/humanize_symbol.rb
63
73
  - lib/ruby-rails-extensions/extensions/in_utc.rb
64
74
  - lib/ruby-rails-extensions/extensions/input.rb
65
75
  - lib/ruby-rails-extensions/extensions/month_and_year.rb
66
76
  - lib/ruby-rails-extensions/extensions/month_year.rb
77
+ - lib/ruby-rails-extensions/extensions/no_keys.rb
78
+ - lib/ruby-rails-extensions/extensions/no_values.rb
79
+ - lib/ruby-rails-extensions/extensions/only_some.rb
67
80
  - lib/ruby-rails-extensions/extensions/overlaps.rb
68
81
  - lib/ruby-rails-extensions/extensions/pipe.rb
69
82
  - lib/ruby-rails-extensions/extensions/presence_bang.rb
83
+ - lib/ruby-rails-extensions/extensions/quarter_dates.rb
84
+ - lib/ruby-rails-extensions/extensions/range_add.rb
85
+ - lib/ruby-rails-extensions/extensions/range_multiply.rb
70
86
  - lib/ruby-rails-extensions/extensions/remove_reserved_keywords.rb
87
+ - lib/ruby-rails-extensions/extensions/safe_parse.rb
88
+ - lib/ruby-rails-extensions/extensions/select_present.rb
89
+ - lib/ruby-rails-extensions/extensions/select_present_join.rb
90
+ - lib/ruby-rails-extensions/extensions/set_to_sentence.rb
71
91
  - lib/ruby-rails-extensions/extensions/to_bool.rb
72
92
  - lib/ruby-rails-extensions/extensions/to_dec.rb
73
93
  - lib/ruby-rails-extensions/extensions/to_i.rb
94
+ - lib/ruby-rails-extensions/extensions/to_local.rb
95
+ - lib/ruby-rails-extensions/extensions/to_negative_i.rb
96
+ - lib/ruby-rails-extensions/extensions/to_nonzero_i.rb
74
97
  - lib/ruby-rails-extensions/extensions/to_or_sentence.rb
98
+ - lib/ruby-rails-extensions/extensions/to_positive_i.rb
75
99
  - lib/ruby-rails-extensions/extensions/to_sort_i.rb
76
100
  - lib/ruby-rails-extensions/extensions/to_x.rb
101
+ - lib/ruby-rails-extensions/extensions/todays_date.rb
102
+ - lib/ruby-rails-extensions/extensions/uniq_map.rb
77
103
  - lib/ruby-rails-extensions/extensions/usd_to_f.rb
78
104
  - lib/ruby-rails-extensions/extensions/usd_to_i.rb
105
+ - lib/ruby-rails-extensions/extensions/weighted_sum.rb
79
106
  - lib/ruby-rails-extensions/extensions/yesno.rb
107
+ - lib/ruby-rails-extensions/extensions/zero_range.rb
80
108
  - lib/ruby-rails-extensions/version.rb
81
109
  homepage: https://github.com/BrandsInsurance/rails-extensions
82
110
  licenses:
@@ -95,9 +123,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
95
123
  version: 2.5.3
96
124
  required_rubygems_version: !ruby/object:Gem::Requirement
97
125
  requirements:
98
- - - ">="
126
+ - - ">"
99
127
  - !ruby/object:Gem::Version
100
- version: '0'
128
+ version: 1.3.1
101
129
  requirements: []
102
130
  rubygems_version: 3.0.3
103
131
  signing_key: