Skip to content

Instantly share code, notes, and snippets.

@artofhuman
Last active March 28, 2018 06:10
Show Gist options
  • Save artofhuman/c23c8b14ab04b4534eb45d870ed13ef4 to your computer and use it in GitHub Desktop.
Save artofhuman/c23c8b14ab04b4534eb45d870ed13ef4 to your computer and use it in GitHub Desktop.
module DatasetFilter
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def filters(filters)
@filters = Array(filters)
end
def filters_list
@filters
end
end
attr_reader :dataset
def initialize(dataset:)
@dataset = dataset
end
def call(filters)
return dataset unless filters
filters.reduce(dataset, &method(:apply_filter))
end
private
def find_filter(filter_name)
self.class.filters_list.find { |i| i.parameters.flatten.last == filter_name }
end
def apply_filter(dataset, param)
filter = find_filter(param[0])
return dataset unless filter
dataset.instance_exec(Hash[*param], &filter)
end
end
# frozen_string_literal: true
RSpec.describe DatasetFilter do
let(:dataset) { Post.dataset }
let!(:post1) { create :post, content: 'Test', created_at: Time.parse('2018-01-01') }
let!(:post2) { create :post, content: 'Qwerty', created_at: Time.parse('2017-01-01') }
let(:filter) do
Class.new do
include DatasetFilter
filters [
->(content:) { where(content: content) },
->(created_at:) { where(created_at: created_at) }
]
end
end
it 'finds only by content' do
result = filter.new(dataset: dataset).call(content: 'Test')
expect(result.to_a).to eq([post1])
end
it 'finds by 2 params' do
result = filter.new(dataset: dataset).call(content: 'Qwerty', created_at: Time.parse('2017-01-01'))
expect(result.to_a).to eq([post2])
end
it 'returns blank result' do
result = filter.new(dataset: dataset).call(content: '123')
expect(result).to be_empty
end
it 'not filters by not registered filter' do
result = filter.new(dataset: dataset).call(missing: 'Test')
expect(result.to_a).to match_array([post1, post2])
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment