Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion apps/web/controllers/vacancies/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,23 @@ def call(params)

private

Container = Module.new do
extend Transproc::Registry
import Transproc::HashTransformations
import Transproc::Coercions
import Transproc::ClassTransformations
end

class Transformer < Transproc::Transformer[Container]
symbolize_keys
map_value :remote, t(:to_boolean)
constructor_inject Queries::Vacancy::SearchQuery
end

def search_query
params[:query] ? search_query_parser.call(params[:query]) : EMPTY_SEARCH_QUERY
query_attributes = params[:query] ? search_query_parser.call(params[:query]) : EMPTY_SEARCH_QUERY
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а еще лучше, я бы сделал так, что квери парсер возвращал бы сразу что надо, вне зависимости от того, что туда передать, что-то в таком духе:

query_attributes = search_query_parser.call(params[:query])

query_attributes # => attributes or initial_attributes

initial_attributes = { remote: nil, position_type: nil, location: nil }
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

я бы в константу это вынес

Transformer.new.call(initial_attributes.merge(query_attributes))
end
end
end
Expand Down
36 changes: 27 additions & 9 deletions lib/core/queries/vacancy.rb
Original file line number Diff line number Diff line change
@@ -1,30 +1,48 @@
# frozen_string_literal: true

module Queries
class Vacancy
class SearchQuery < Dry::Struct
attribute :remote, Core::Types::Strict::Bool.optional.default(nil)
attribute :position_type, Core::Types::VacancyPositionTypes.optional.default(nil)
attribute :location, Core::Types::Strict::String.optional.default(nil)
end
end

class Vacancy
attr_reader :repo

def initialize(repo = VacancyRepository.new)
@repo = repo
end

def all_with_contact(limit:, page:)
all_with_contact_relation(limit: limit, page: page).to_a
def all_with_contact(limit:, page:, search_query:)
all_with_contact_relation(limit: limit, page: page, search_query: search_query).to_a
end

def pager_for_all_with_contact(limit:, page:)
def pager_for_all_with_contact(limit:, page:, search_query:)
Hanami::Pagination::Pager.new(
all_with_contact_relation(limit: limit, page: page).pager
all_with_contact_relation(limit: limit, page: page, search_query: search_query).pager
)
end

private

def all_with_contact_relation(limit:, page:)
repo.aggregate(:contact)
.where(published: true, archived: false, deleted_at: nil)
.map_to(::Vacancy).order { created_at.desc }
.per_page(limit).page(page || 1)
QUERY_MODIFIERS = {
remote: ->(query, filter_value) { query.where(remote_available: filter_value) },
position_type: ->(query, filter_value) { query.where(position_type: filter_value) },
location: ->(query, filter_value) { query.where { location.ilike("%#{filter_value}%") } }
}.freeze

def all_with_contact_relation(limit:, page:, search_query:)
query = repo.aggregate(:contact)
.where(published: true, archived: false, deleted_at: nil)
search_query.to_h.each do |key, value|
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

реально оптимизировать этот кусок? что бы при nil код не выполнялся?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не совсем понял вопрос

Copy link

@JuPlutonic JuPlutonic Oct 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

может быть:

if search_query
 ...
end
search_query.to_h.each do |key, value|

modifier = QUERY_MODIFIERS[key]
query = modifier.call(query, value) if modifier && value
end
query.map_to(::Vacancy).order { created_at.desc }
.per_page(limit).page(page || 1)
end
end
end
10 changes: 7 additions & 3 deletions lib/vacancies/operations/list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ class List < ::Libs::Operation

PAGINATION_LIMIT = 10

def call(search_query: {}, page: 1) # rubocop:disable Lint/UnusedMethodArgument
pager = vacancy_query.pager_for_all_with_contact(limit: PAGINATION_LIMIT, page: page || 1)
result = vacancy_query.all_with_contact(limit: PAGINATION_LIMIT, page: page || 1)
def call(search_query: {}, page: 1)
pager = vacancy_query.pager_for_all_with_contact(
limit: PAGINATION_LIMIT,
page: page || 1,
search_query: search_query
)
result = vacancy_query.all_with_contact(limit: PAGINATION_LIMIT, page: page || 1, search_query: search_query)

Success(result: result, pager: pager)
end
Expand Down
56 changes: 54 additions & 2 deletions spec/core/queries/vacancy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,27 @@

RSpec.describe Queries::Vacancy, type: :query do
let(:repo) { described_class.new }
let(:query_attributes) { return { remote: nil, position_type: nil, location: nil } }
let(:search_query) { Queries::Vacancy::SearchQuery.new }

describe '#all_with_contact' do
subject { repo.all_with_contact(limit: 10, page: 1) }
subject { repo.all_with_contact(limit: 10, page: 1, search_query: search_query) }

before { Fabricate.create(:vacancy, published: published, archived: archived, deleted_at: deleted_at) }
let(:remote_available) { nil }
let(:position_type) { nil }
let(:location) { nil }

before do
Fabricate.create(
:vacancy,
published: published,
archived: archived,
deleted_at: deleted_at,
remote_available: remote_available,
position_type: position_type,
location: location
)
end

context 'when vacancy published and not archived or deleted' do
let(:published) { true }
Expand All @@ -16,6 +32,42 @@
it { expect(subject.count).to eq(1) }
it { expect(subject).to all(be_a(Vacancy)) }
it { expect(subject.first.contact).to be_a(Contact) }

context 'and remote in search_query is true' do
let(:search_query) { Queries::Vacancy::SearchQuery.new(query_attributes.merge(remote: true)) }

it { expect(subject).to eq([]) }

context 'and remote_available in record is true as well' do
let(:remote_available) { true }

it { expect(subject.count).to eq(1) }
end
end

context 'and position_type in search_query is equal "other"' do
let(:search_query) { Queries::Vacancy::SearchQuery.new(query_attributes.merge(position_type: 'other')) }

it { expect(subject).to eq([]) }

context 'and position_type in record is "other" as well' do
let(:position_type) { 'other' }

it { expect(subject.count).to eq(1) }
end
end

context 'and location in search query is not empty' do
let(:search_query) { Queries::Vacancy::SearchQuery.new(query_attributes.merge(location: 'VASYUKI')) }

it { expect(subject).to eq([]) }

context 'and location in record includes location from search query' do
let(:location) { 'New Vasyuki' }

it { expect(subject.count).to eq(1) }
end
end
end

context 'when vacancy published and archived' do
Expand Down
2 changes: 1 addition & 1 deletion spec/web/controllers/vacancies/index_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
it { expect(subject).to be_success }

it do
expect(operation).to receive(:call).with(page: nil, search_query: { remote: 'true', text: 'search text' })
expect(operation).to receive(:call).with(page: nil, search_query: Queries::Vacancy::SearchQuery.new(remote: true, location: nil, position_type: nil))
subject
end
end
Expand Down