Skip to content

Commit 1ac5c74

Browse files
authored
Merge pull request #39 from asusikov/33-filters-in-query-object
Filters by remote_availibity, location, position_type in query object
2 parents 4315dfc + df683d8 commit 1ac5c74

File tree

9 files changed

+138
-12
lines changed

9 files changed

+138
-12
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@
55
.ruby-version
66
.env.dev
77
.env.development
8+
9+
.direnv/
10+
.envrc

apps/web/controllers/vacancies/index.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ class Index
99

1010
include Import[
1111
'libs.search_query_parser',
12-
operation: 'vacancies.operations.list'
12+
operation: 'vacancies.operations.list',
13+
search_options_mapper: 'vacancies.mappers.search_options',
1314
]
1415

1516
EMPTY_SEARCH_QUERY = {}.freeze
@@ -35,7 +36,9 @@ def call(params)
3536
private
3637

3738
def search_query
38-
params[:query] ? search_query_parser.call(params[:query]) : EMPTY_SEARCH_QUERY
39+
query_attributes = params[:query] ? search_query_parser.call(params[:query]) : EMPTY_SEARCH_QUERY
40+
initial_attributes = { remote: nil, position_type: nil, location: nil }
41+
search_options_mapper.call(initial_attributes.merge(query_attributes))
3942
end
4043
end
4144
end

lib/core/queries/vacancy.rb

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,35 @@ def initialize(repo = VacancyRepository.new)
88
@repo = repo
99
end
1010

11-
def all_with_contact(limit:, page:)
12-
all_with_contact_relation(limit: limit, page: page).to_a
11+
def all_with_contact(limit:, page:, search_query:)
12+
all_with_contact_relation(limit: limit, page: page, search_query: search_query).to_a
1313
end
1414

15-
def pager_for_all_with_contact(limit:, page:)
15+
def pager_for_all_with_contact(limit:, page:, search_query:)
1616
Hanami::Pagination::Pager.new(
17-
all_with_contact_relation(limit: limit, page: page).pager
17+
all_with_contact_relation(limit: limit, page: page, search_query: search_query).pager
1818
)
1919
end
2020

2121
private
2222

23+
QUERY_MODIFIERS = {
24+
remote: ->(query, filter_value) { query.where(remote_available: filter_value) },
25+
position_type: ->(query, filter_value) { query.where(position_type: filter_value) },
26+
location: ->(query, filter_value) { query.where { location.ilike("%#{filter_value}%") } }
27+
}.freeze
28+
29+
def new_all_with_contact_relation(limit:, page:, search_query:)
30+
query = repo.aggregate(:contact)
31+
.where(published: true, archived: false, deleted_at: nil)
32+
search_query.to_h.each do |key, value|
33+
modifier = QUERY_MODIFIERS[key]
34+
query = modifier.call(query, value) if modifier && value
35+
end
36+
query.map_to(::Vacancy).order { created_at.desc }
37+
.per_page(limit).page(page || 1)
38+
end
39+
2340
def all_with_contact_relation(limit:, page:)
2441
repo.aggregate(:contact)
2542
.where(published: true, deleted_at: nil)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# frozen_string_literal: true
2+
3+
module Vacancies
4+
module Entities
5+
class SearchOptions < Dry::Struct
6+
attribute :remote, Core::Types::Strict::Bool.optional.default(nil)
7+
attribute :position_type, Core::Types::VacancyPositionTypes.optional.default(nil)
8+
attribute :location, Core::Types::Strict::String.optional.default(nil)
9+
end
10+
end
11+
end
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# frozen_string_literal: true
2+
3+
module Vacancies
4+
module Mappers
5+
Container = Module.new do
6+
extend Transproc::Registry
7+
import Transproc::HashTransformations
8+
import Transproc::Coercions
9+
import Transproc::ClassTransformations
10+
end
11+
12+
class SearchOptions < Transproc::Transformer[Container]
13+
symbolize_keys
14+
map_value :remote, t(:to_boolean)
15+
constructor_inject ::Vacancies::Entities::SearchOptions
16+
end
17+
end
18+
end

lib/vacancies/operations/list.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@ class List < ::Libs::Operation
99

1010
PAGINATION_LIMIT = 10
1111

12-
def call(search_query: {}, page: 1) # rubocop:disable Lint/UnusedMethodArgument
13-
pager = vacancy_query.pager_for_all_with_contact(limit: PAGINATION_LIMIT, page: page || 1)
14-
result = vacancy_query.all_with_contact(limit: PAGINATION_LIMIT, page: page || 1)
12+
def call(search_query: {}, page: 1)
13+
pager = vacancy_query.pager_for_all_with_contact(
14+
limit: PAGINATION_LIMIT,
15+
page: page || 1,
16+
search_query: search_query
17+
)
18+
result = vacancy_query.all_with_contact(limit: PAGINATION_LIMIT, page: page || 1, search_query: search_query)
1519

1620
Success(result: result, pager: pager)
1721
end

spec/core/queries/vacancy_spec.rb

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,27 @@
22

33
RSpec.describe Queries::Vacancy, type: :query do
44
let(:repo) { described_class.new }
5+
let(:query_attributes) { return { remote: nil, position_type: nil, location: nil } }
6+
let(:search_query) { Vacancies::Entities::SearchOptions.new }
57

68
describe '#all_with_contact' do
7-
subject { repo.all_with_contact(limit: 10, page: 1) }
9+
subject { repo.all_with_contact(limit: 10, page: 1, search_query: search_query) }
810

9-
before { Fabricate.create(:vacancy, published: published, archived_at: archived_at, deleted_at: deleted_at) }
11+
let(:remote_available) { nil }
12+
let(:position_type) { nil }
13+
let(:location) { nil }
14+
15+
before do
16+
Fabricate.create(
17+
:vacancy,
18+
published: published,
19+
archived: archived,
20+
deleted_at: deleted_at,
21+
remote_available: remote_available,
22+
position_type: position_type,
23+
location: location
24+
)
25+
end
1026

1127
context 'when vacancy published and not archived or deleted' do
1228
let(:published) { true }
@@ -16,6 +32,42 @@
1632
it { expect(subject.count).to eq(1) }
1733
it { expect(subject).to all(be_a(Vacancy)) }
1834
it { expect(subject.first.contact).to be_a(Contact) }
35+
36+
context 'and remote in search_query is true' do
37+
let(:search_query) { Vacancies::Entities::SearchOptions.new(query_attributes.merge(remote: true)) }
38+
39+
it { expect(subject).to eq([]) }
40+
41+
context 'and remote_available in record is true as well' do
42+
let(:remote_available) { true }
43+
44+
it { expect(subject.count).to eq(1) }
45+
end
46+
end
47+
48+
context 'and position_type in search_query is equal "other"' do
49+
let(:search_query) { Vacancies::Entities::SearchOptions.new(query_attributes.merge(position_type: 'other')) }
50+
51+
it { expect(subject).to eq([]) }
52+
53+
context 'and position_type in record is "other" as well' do
54+
let(:position_type) { 'other' }
55+
56+
it { expect(subject.count).to eq(1) }
57+
end
58+
end
59+
60+
context 'and location in search query is not empty' do
61+
let(:search_query) { Vacancies::Entities::SearchOptions.new(query_attributes.merge(location: 'VASYUKI')) }
62+
63+
it { expect(subject).to eq([]) }
64+
65+
context 'and location in record includes location from search query' do
66+
let(:location) { 'New Vasyuki' }
67+
68+
it { expect(subject.count).to eq(1) }
69+
end
70+
end
1971
end
2072

2173
context 'when vacancy published and archived' do
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe Vacancies::Mappers::SearchOptions, type: :mapper do
4+
subject { described_class.new.call(search_options_hash) }
5+
6+
let(:search_options_hash) { { remote: nil, position_type: 'other', location: 'New Vasyuki' } }
7+
8+
it { expect(subject).to be_a(Vacancies::Entities::SearchOptions) }
9+
it { expect(subject.position_type).to eq(search_options_hash[:position_type]) }
10+
it { expect(subject.location).to eq(search_options_hash[:location]) }
11+
12+
context 'when remote is string equaled "true"' do
13+
let(:search_options_hash) { { remote: 'true', position_type: nil, location: nil } }
14+
15+
it { expect(subject.remote).to be_truthy }
16+
end
17+
end

spec/web/controllers/vacancies/index_spec.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@
2020

2121
context 'when params inlcludes query param' do
2222
let(:params) { { query: 'remote:true search text' } }
23+
let(:search_query) { Vacancies::Entities::SearchOptions.new(remote: true, location: nil, position_type: nil) }
2324

2425
it { expect(subject).to be_success }
2526

2627
it do
27-
expect(operation).to receive(:call).with(page: nil, search_query: { remote: 'true', text: 'search text' })
28+
expect(operation).to receive(:call).with(page: nil, search_query: search_query)
2829
subject
2930
end
3031
end

0 commit comments

Comments
 (0)