Skip to content

Instantly share code, notes, and snippets.

@voising
Last active November 13, 2019 06:08
Show Gist options
  • Save voising/5822293c6386bb1f600b8b13b27c9100 to your computer and use it in GitHub Desktop.
Save voising/5822293c6386bb1f600b8b13b27c9100 to your computer and use it in GitHub Desktop.
Marketplace - Search by rate & tags - Controller - Crystal
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