Rails 6 adds Array#including, Array#excluding, Enumerable#including, Enumerable#excluding


Rails 6 has made many new additions to Array and Enumerable:

  • Array#including
  • Array#excluding
  • Enumerable#including
  • Enumerable#excluding

Array#excluding and Enumerable#excluding

There are times, when we would like to remove an element from a collection. On Array or Enumerable, we could achieve this by collectionA - collectionB. Rails offers a more readable approach to these via Array#without and Enumerable#without

# current_user is set to currently logged in user 
all_active_users = User.where(status: "active")
all_active_users.without(current_user)
# This returns all active users excluding  
# the currently logged in user

# More simpler examples
[ 1, 2, 3, 4, 5 ].without(4)
#=>  [1, 2, 3, 5]

# Without also takes multiple arguments to be removed
[ 1, 2, 3, 4, 5 ].without(4, 5)
#=>  [1, 2, 3]  

With the introduction of its counter parts #including, we can now perform this same functionality as #excluding

[ 1, 2, 3, 4, 5 ].excluding(4)
#=>  [1, 2, 3, 5]

[ 1, 2, 3, 4, 5 ].excluding(4, 5)
#=>  [1, 2, 3]  

With this addition, it also fixes an issue where the exclusion would fail if we passed an Array. We can now also successfully pass collections to be excluded.

# Before
[ 1, 2, 3, 4, 5 ].excluding([4, 5])
#=>  [1, 2, 3, 4, 5]

# After
[ 1, 2, 3, 4, 5 ].excluding([4, 5])
#=>  [1, 2, 3]

# Exclude collections
all_active_users = User.where(status: "active")
high_risk_users = User.where(risk: true)
all_active_users.excluding(high_risk_users)
# => User collection with active users who are not high risk  

The without method is still available and is an alias to excluding.

Array#including and Enumerable#including

To match their counter parts #excluding we can now perform #including on Array and Enumerable. This is short hand and more readable form of addition of two collections.

[ 1, 2, 3 ].including([4, 5])
# =>  [1, 2, 3, 4, 5]

# Accepts and handles passed Arrays 
%w{Ruby Pearl}.including(%w{Java})
# => ["Ruby", "Pearl", "Java"]

# We can also include on collections
all_active_users = User.where(status: "active")
low_risk_users = User.where(risk: false)
all_active_users.including(low_risk_users)
# => User collection with active users as well as who are not high risk

As we can see, #including and #excluding add an easier and more readable way to work with collection addition and removals.