app/controllers/search_controller.rb
# frozen_string_literal: true
class SearchController < BaseController
# callbacks
before_action :check_params
skip_before_action :require_authentication, only: [:entries]
def entries
boost_by_recency = { created_at: { scale: '4d', decay: 0.5 } }
fields = ['title^8', 'body^3', 'url^4', 'categories']
entries = Entry.pagy_search(params[:q], where: build_filters, boost_by_recency: boost_by_recency, order: build_order, fields: fields).results
@pagy, @entries = pagy_searchkick(entries)
json_response_with_serializer(@entries, Serializer::ENTRY)
rescue StandardError => e
Rails.logger.error(e)
json_error_response('SearchEntriesError', e.message, 500)
end
def feeds
fields = ['title^8', 'description', 'url^4']
feeds = Feed.pagy_search(params[:q], boost_by: %i[entries_count rank], fields: fields).results
@pagy, @feeds = pagy_searchkick(feeds)
json_response_with_serializer(@feeds, Serializer::FEED)
rescue StandardError => e
Rails.logger.error(e)
json_error_response('SearchFeedsError', e.message, 500)
end
private
def build_order
order = {}
order[:published_at] = entries_params[:order] if entries_params[:order].present?
order
end
def build_filters
filters = {}
range = {}
range[:gte] = Time.parse(entries_params[:from]) if entries_params[:from].present?
range[:lte] = Time.parse(entries_params[:to]) if entries_params[:to].present?
filters[:feed_id] = entries_params[:feed_id] if entries_params[:feed_id].present?
filters[:published_at] = range
filters
end
def entries_params
params.permit(:q, :from, :to, :feed_id, :order)
end
def check_params
unless entries_params[:q].present?
json_error_response('Validation Failed', 'missing q param', :unprocessable_entity)
return
end
if entries_params[:order].present? && !%w[asc desc].include?(entries_params[:order])
json_error_response('Validation Failed', 'order param must be asc/desc', :unprocessable_entity)
end
end
end