🔃 Simple wrapper to filter array using Ruby and simple predicate conditions
MIT License
Because in sometimes, we need filter array passing conditions. This gem simplify this work.
Version | Documentation |
---|---|
unreleased | https://github.com/thadeu/recollect-array/blob/main/README.md |
kind | branch | ruby |
---|---|---|
unreleased | main | >= 2.5.8, <= 3.1.x |
Use bundle
bundle add recollect-array
or add this line to your application's Gemfile.
gem 'recollect-array'
and then, require module
require 'recollect/array'
Without configuration, because we use only Ruby.
Type | Suffix | Value |
---|---|---|
Equal | eq | Anywhere |
NotEqual | noteq | Anywhere |
Contains | cont | Anywhere |
NotContains | notcont | Anywhere |
Included | in | Anywhere |
NotIncluded | notin | Anywhere |
Start | start | Anywhere |
NotStart | notstart | Anywhere |
End | end | Anywhere |
NotEnd | notend | Anywhere |
LessThan | lt | Anywhere |
LessThanEqual | lteq | Anywhere |
GreaterThan | gt | Anywhere |
GreaterThanEqual | gteq | Anywhere |
Below predicates works only when value is Hash
Type | Suffix | Value |
---|---|---|
NotEqual | not_eq | Hash |
NotContains | not_cont | Hash |
NotIncluded | not_in | Hash |
NotStart | not_start | Hash |
NotEnd | not_end | Hash |
data = [
{
id: 1,
name: 'Test #1',
email: '[email protected]',
schedule: { all_day: true },
numbers: %w[1 2],
active: true,
count: 9
},
{
id: 2,
name: 'Test #2',
email: '[email protected]',
schedule: { all_day: false },
numbers: %w[3 4],
active: true,
count: 10
},
{
id: 3,
name: 'Test #3',
email: '[email protected]',
schedule: { all_day: false },
numbers: %w[5 6],
active: false,
count: 99
}
]
You can use one or multiples predicates in your filter. We see some use cases.
Equal
filters = {
active: {
eq: true
}
}
collection = Recollect::Array.filter(data, filters)
NotEqual
filters = {
active: {
# noteq or not_eq
not_eq: true
}
}
collection = Recollect::Array.filter(data, filters)
Nested Hash Paths
filters = {
'schedule.all_day': {
eq: true
}
}
collection = Recollect::Array.filter(data, filters)
Nested Array Paths
Note the
.0
filters = {
'numbers.0': {
eq: '3'
}
}
collection = Recollect::Array.filter(data, filters)
filters = {
numbers: {
in: '3' # or in: ['3']
}
}
collection = Recollect::Array.filter(data, filters)
Using default Equal predicate.
Recollect::Array.filter(data, numbers: 3)
Recollect::Array.filter(data, active: true)
Recollect::Array.filter(data, id: 3)
If array, you can navigate into self, using property.NUMBER.property
data = [
{
schedules: [
{
opened: true,
all_day: true
},
{
opened: false,
all_day: true
}
]
},
{
schedules: [
{
opened: false,
all_day: true
},
{
opened: false,
all_day: true
}
]
}
]
filters = {
'schedules.0.opened': {
eq: true
}
}
# OR
filters = {
'schedules[0]opened': {
eq: true
}
}
# OR
filters = {
'schedules.[0].opened': {
eq: true
}
}
collection = Recollect::Array.filter(data, filters)
# [{ schedules: [{ opened: true, all_day: true }, { opened: false, all_day: true }] }]
Amazing, you can pass a Callable value as value, like this.
filters = {
'schedules.[0].opened': {
eq: -> { true }
}
}
# OR a Module
module ActiveTruthy
def self.call = true
end
module NumbersAvailable
def self.call = %w[1 2]
end
filters = {
'schedules.[0].opened': {
eq: ActiveTruthy
},
numbers: {
in: NumbersAvailable
}
}
# OR a Class
class ActiveFalsey
def self.call = false
end
filters = {
'schedules.[0].opened': {
eq: ActiveFalsey
}
}
collection = Recollect::Array.filter(data, filters)
Combine conditions
Yes, you can combine one or multiple predicates to filter you array.
filters = {
active: { eq: true },
numbers: {
in: %w[5],
not_in: '10'
},
email: {
cont: 'email1',
not_cont: '@gmail'
},
'schedule.all_day': {
in: [true, false]
}
}
collection = Recollect::Array.filter(data, filters)
Equal
filters = { active_eq: true }
collection = Recollect::Array.filter(data, filters)
NotEqual
filters = { active_noteq: true }
collection = Recollect::Array.filter(data, filters)
Nested Hash Paths
filters = { 'schedule.all_day_eq': false }
collection = Recollect::Array.filter(data, filters)
Nested Array Paths
Note the
.0
filters = { 'numbers.0_eq': '3' }
collection = Recollect::Array.filter(data, filters)
filters = { numbers_in: ['1'] }
collection = Recollect::Array.filter(data, filters)
expect(collection.size).to eq(1)
Combine conditions
Yes, you can combine one or multiple predicates to filter you array.
filters = {
active_noteq: true,
numbers_in: %w[5],
email_cont: 'test3',
'schedule.all_day_eq': false
}
collection = Recollect::Array.filter(data, filters)
Receive querystring in your route
Like Ransack, imagine that you receive an querystring and you want to filter your Array. So, you can to do something like this.
But security is your responsability, ok? Let's go!
# receive querystring in your route
querystring = "active_noteq=true&numbers_in=5&email_cont=test3&schedule.all_day_eq=false"
# parse querystring and transform to Hash
params = URI.decode_www_form(querystring).to_h
# filter your collection using params directly.
collection = Recollect::Array.filter(data, filters)
# Beautiful, right?
user = {
id: 1,
name: 'Test #1',
email: '[email protected]',
schedule: { all_day: true },
numbers: %w[1 2],
active: true,
count: 9
}
result = Recollect::Hashie.get(user, 'id')
-> 1
result = Recollect::Hashie.get(user, 'schedule.all_day')
-> true
result = Recollect::Hashie.get(user, 'numbers')
-> ['1', '2']
result = Recollect::Hashie.get(user, 'numbers.0')
-> 1
result = Recollect::Hashie.get(user, 'numbers[0]')
-> 1
result = Recollect::Hashie.get(user, 'numbers[0][1]')
result = Recollect::Hashie.get(user, 'numbers.[0].[1]')
users = [
{
id: 1,
name: 'Test #1',
email: '[email protected]',
schedule: { all_day: true },
numbers: %w[1 2],
active: true,
count: 9
},
{
id: 2,
name: 'Test #1',
email: '[email protected]',
schedule: { all_day: true },
numbers: %w[1 2],
active: true,
count: 9
}
]
result = Recollect::Array.pluck(users, 'id')
$ -> [1, 2]
result = Recollect::Array.pluck(users, 'schedule.all_day')
$ -> [true, true]
After checking out the repo, run bin/setup
to install dependencies. Then, run bundle exec rspec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/thadeu/recollect-array. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
The gem is available as open source under the terms of the MIT License.