Last active
November 13, 2019 06:08
-
-
Save voising/5822293c6386bb1f600b8b13b27c9100 to your computer and use it in GitHub Desktop.
Marketplace - Search by rate & tags - Controller - Crystal
This file contains hidden or 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
require "cache" | |
class ProductController < ApplicationController | |
getter filter_by_tags : Bool? | |
def index | |
# NO TAGS -> CACHE | |
if !filter_by_tags? && !filter_by_rate? | |
# CACHE | |
cache_response | |
else | |
# OTHERWISE APPEND CLAUSE TO QUERY | |
extra_clause = "" | |
extra_clause += rate_where_clause if filter_by_rate? | |
extra_clause += " GROUP BY products.id " | |
extra_clause += tags_having_clause if filter_by_tags? | |
extra_clause += " LIMIT 100" | |
products = ProductQuery.all(extra_clause) | |
render_json({ | |
data: products | |
}) | |
end | |
end | |
def filter_by_rate? | |
params["rate[]"]? | |
end | |
def filter_by_tags? | |
return @filter_by_tags unless @filter_by_tags.nil? | |
@filter_by_tags ||= TagKinds.values | |
.map{ |tag| tag.to_s.downcase } | |
.any?{ |tag| params["#{tag}[]"]? } | |
end | |
def rate_where_clause | |
min, max = params.fetch_all("rate[]") | |
return "" unless min =~ /\A[\d\.]+\Z/ | |
return "" unless max =~ /\A[\d\.]+\Z/ | |
%{ WHERE rates.amount BETWEEN #{min.to_f} AND #{max.to_f}} | |
end | |
def tags_having_clause | |
havings = [] of String | |
TagKinds.values.map{|tag|tag.to_s.downcase}.each do |tag| | |
if params["#{tag}[]"]? | |
tags = params.fetch_all("#{tag}[]") | |
if tags.size > 0 && tags.all?{|tag|tag =~ /\A[\d\.]+\Z/} | |
havings.push %{ARRAY_AGG(taggables.tag_id) && ARRAY[#{tags.join(',')}]::bigint[]} | |
end | |
end | |
end | |
if havings.size > 0 | |
" HAVING #{havings.join(" AND ")}" | |
else | |
"" | |
end | |
end | |
def cache_response | |
cache = Cache::RedisStore(String, String).new(expires_in: 15.minutes) | |
products = cache.fetch("products#index-limit-100") do | |
ProductQuery.all("GROUP BY products.id LIMIT 100").to_json | |
end | |
context.response.content_type = "application/json" | |
"{data: #{products}}" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment