From c8847c17a7c9ae75c44c522c56ccd9c5fca25ea7 Mon Sep 17 00:00:00 2001 From: Dana Sherson Date: Wed, 5 Jun 2019 17:25:18 +1000 Subject: Add compact_blank shortcut for reject(&:blank?) I frequently find myself having to .compact but for blank. which means on an array reject(&:blank?) (this is fine), or, on a hash `.reject { |_k, v| v.blank? }` which is slightly more frustrating and i usually write it as .reject(&:blank?) first and am confused when it's trying to check if the keys are blank. I've added the analagous .compact_blank! where there's a reject! to build on (there's also a reject! in Set, but there's no other core_ext touching Set so i've left that alone) --- activesupport/CHANGELOG.md | 5 +++ .../lib/active_support/core_ext/enumerable.rb | 46 ++++++++++++++++++++++ activesupport/test/core_ext/enumerable_test.rb | 24 +++++++++++ 3 files changed, 75 insertions(+) (limited to 'activesupport') diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 955eb7eef9..6256fb8c86 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,8 @@ +* Add `compact_blank` for those times when you want to remove #blank? values from + an Enumerable (also `compact_blank!` on Hash, Array, ActionController::Parameters) + + *Dana Sherson* + * `delegate_missing_to` would raise a `DelegationError` if the object delegated to was `nil`. Now the `allow_nil` option has been added to enable the user to specify they want `nil` returned in this case. diff --git a/activesupport/lib/active_support/core_ext/enumerable.rb b/activesupport/lib/active_support/core_ext/enumerable.rb index 4675c41936..728d332306 100644 --- a/activesupport/lib/active_support/core_ext/enumerable.rb +++ b/activesupport/lib/active_support/core_ext/enumerable.rb @@ -148,6 +148,41 @@ module Enumerable map { |element| element[keys.first] } end end + + # Returns a new +Array+ without the blank items. + # Uses Object#blank? for determining if an item is blank. + # + # [1, "", nil, 2, " ", [], {}, false, true].compact_blank + # # => [1, 2, true] + # + # Set.new([nil, "", 1, 2]) + # # => [2, 1] (or [1, 2]) + # + # When called on a +Hash+, returns a new +Hash+ without the blank values. + # + # { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank + # #=> { b: 1, f: true } + def compact_blank + reject(&:blank?) + end +end + +class Hash + # Hash#reject has its own definition, so this needs one too. + def compact_blank #:nodoc: + reject { |_k, v| v.blank? } + end + + # Removes all blank values from the +Hash+ in place and returns self. + # Uses Object#blank? for determining if a value is blank. + # + # h = { a: "", b: 1, c: nil, d: [], e: false, f: true } + # h.compact_blank! + # # => { b: 1, f: true } + def compact_blank! + # use delete_if rather than reject! because it always returns self even if nothing changed + delete_if { |_k, v| v.blank? } + end end class Range #:nodoc: @@ -185,4 +220,15 @@ class Array #:nodoc: super end end + + # Removes all blank elements from the +Array+ in place and returns self. + # Uses Object#blank? for determining if an item is blank. + # + # a = [1, "", nil, 2, " ", [], {}, false, true] + # a.compact_blank! + # # => [1, 2, true] + def compact_blank! + # use delete_if rather than reject! because it always returns self even if nothing changed + delete_if(&:blank?) + end end diff --git a/activesupport/test/core_ext/enumerable_test.rb b/activesupport/test/core_ext/enumerable_test.rb index 381b5a1f32..a9bf4b82f4 100644 --- a/activesupport/test/core_ext/enumerable_test.rb +++ b/activesupport/test/core_ext/enumerable_test.rb @@ -242,4 +242,28 @@ class EnumerableTests < ActiveSupport::TestCase ]) assert_equal [[5, 99], [15, 0], [10, 50]], payments.pluck(:dollars, :cents) end + + def test_compact_blank + values = GenericEnumerable.new([1, "", nil, 2, " ", [], {}, false, true]) + + assert_equal [1, 2, true], values.compact_blank + end + + def test_array_compact_blank! + values = [1, "", nil, 2, " ", [], {}, false, true] + values.compact_blank! + + assert_equal [1, 2, true], values + end + + def test_hash_compact_blank + values = { a: "", b: 1, c: nil, d: [], e: false, f: true } + assert_equal({ b: 1, f: true }, values.compact_blank) + end + + def test_hash_compact_blank! + values = { a: "", b: 1, c: nil, d: [], e: false, f: true } + values.compact_blank! + assert_equal({ b: 1, f: true }, values) + end end -- cgit v1.2.3