ruby-rails-extensions 0.1.0 → 0.2.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: 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: