Simple wrapper to filter array using Ruby and simple predicate conditions
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-arrayor 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 | 
Think that your data seems like this.
data = [
  {
    id: 1,
    name: 'Test #1',
    email: 'test1@email1.com',
    schedule: { all_day: true },
    numbers: %w[1 2],
    active: true,
    count: 9
  },
  {
    id: 2,
    name: 'Test #2',
    email: 'test2@email2.com',
    schedule: { all_day: false },
    numbers: %w[3 4],
    active: true,
    count: 10
  },
  {
    id: 3,
    name: 'Test #3',
    email: 'test3@email3.com',
    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? π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.