Created
July 20, 2023 01:18
-
-
Save CharlyJazz/79898de6a1f252f1f526e3f5cdc238ab to your computer and use it in GitHub Desktop.
prueba.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Api::CarSearch | |
include SearchObject.module(:paging) | |
include SearchObject.module(:sorting) | |
per_page 1 | |
min_per_page 1 | |
max_per_page 50 | |
sort_by :price | |
option(:price_min) { |scope, value| scope.where('price > ?', value) } | |
option(:price_max) { |scope, value| scope.where('price < ?', value) } | |
# https://stackoverflow.com/questions/11823689/how-to-make-sure-a-record-is-always-at-the-top-in-a-given-resultset-in-mysql | |
# https://stackoverflow.com/questions/48743316/ruby-on-rails-active-record-sort-and-put-specific-row-to-the-top | |
# https://stackoverflow.com/questions/23620615/how-to-sort-activerecord-query-by-specific-prority | |
# Implement Priority sending using the order clause. | |
# ------ | |
# With this approach I can paginate easily using SQL and avoid merge manually differents sources of cars and then paginate it manually | |
# ------ | |
# This technique are respeting the price_min and price_max filters but the perfect match and good match | |
# will be in the top no matter if the price dont fit with the filter rules | |
def initialize(options={}) | |
counter_priority = 0 | |
super options.merge(scope: Car.order( | |
Arel.sql( | |
" | |
CASE | |
#{ | |
options[:top_results_id][:car_perfect_match_ids].map do |id| | |
counter_priority += 1 | |
"WHEN (id = #{id}) THEN #{counter_priority} " | |
end.join(' ') + | |
options[:top_results_id][:car_good_match_ids].map do |id| | |
counter_priority += 1 | |
"WHEN (id = #{id}) THEN #{counter_priority} " | |
end.join(' ') + | |
options[:top_results_id][:car_external_recommendation_ids].map do |id| | |
counter_priority += 1 | |
"WHEN (id = #{id}) THEN #{counter_priority} " | |
end.join(' ') | |
} | |
END ASC" | |
) | |
).all) | |
end | |
end | |
class Api::CarSearchController < ApplicationController | |
def index | |
@user = User.find(params[:user_id]) | |
# 1. On top it should be cars with perfect_match label. This cars have match | |
# with user preferred car brands ( user.preferred_brands.include?(car.brand) == true) | |
# and with preferred price (user.preferred_price_range.include?(car.price) == true). | |
car_perfect_match_ids = (20..25).to_a | |
# 2. Then we should have good_match offers. These offers have the only user | |
# preferred car brands (user.preferred_brands.include?(car.brand) == true). | |
car_good_match_ids = (40..45).to_a | |
# 3. Then goes top 5 cars suggested by external recommendation service API | |
# (they can also be matched as perfect and good matches). | |
car_external_recommendation_ids = (60..65).to_a | |
# 4. Then goes all other cars sorted by price (ASC). | |
@search = Api::CarSearch.new( | |
filters: get_search_filter_params.merge( | |
{ sort: 'price asc' } | |
), | |
page: params[:page], | |
per_page: params[:per_page], | |
top_results_id: { | |
car_perfect_match_ids: car_perfect_match_ids, | |
car_good_match_ids: car_good_match_ids, | |
car_external_recommendation_ids: car_external_recommendation_ids | |
} | |
) | |
end | |
private | |
def get_search_filter_params | |
params.slice(:user_id, :query, :price_min, :price_max, :free) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment