Skip to content
Snippets Groups Projects
Commit cf47fc8a authored by Mauricio Giacomini Girardello's avatar Mauricio Giacomini Girardello
Browse files

Merge branch 'master' of gitlab.c3sl.ufpr.br:portalmec/portalmec

parents ad1ea726 9f52084a
No related branches found
No related tags found
No related merge requests found
attributes:
- content
- foreign_key
- inheritance
disconnected: true
filename: erd
filetype: pdf
indirect: true
inheritance: true
markup: true
notation: bachman
orientation: horizontal
polymorphism: false
sort: true
warn: true
title: PortalMEC
exclude: null
only: null
prepend_primary: false
class V1::SearchController < ApplicationController
before_action :set_search
# GET v1/search
# GET v1/search.json
def index
begin
render json: ActiveModel::ArraySerializer.new(search_service.fetch), status: :ok
rescue => e
if e.message == "Invalid search"
render json: @search.errors, status: :bad_request
else
render nothing: true, status: :internal_server_error
puts e.message
puts e.backtrace
end
render json: ActiveModel::ArraySerializer.new(SearchService.search(@search, current_user)), status: :ok
rescue => e
if e.message == 'Invalid search'
render json: @search.errors, status: :bad_request
else
render nothing: true, status: :internal_server_error
end
end
# GET v1/search/autocomplete
# GET v1/search/autocomplete.json
def autocomplete
begin
render json: ActiveModel::ArraySerializer.new(search_service.autocomplete), status: :ok
rescue => e
if e.message == "Invalid search"
render json: @search.errors, status: :bad_request
else
render nothing: true, status: :internal_server_error
puts e.message
puts e.backtrace
end
render json: ActiveModel::ArraySerializer.new(SearchService.autocomplete(@search, current_user)), status: :ok
rescue => e
if e.message == 'Invalid search'
render json: @search.errors, status: :bad_request
else
render nothing: true, status: :internal_server_error
end
end
......@@ -39,9 +30,4 @@ class V1::SearchController < ApplicationController
def set_search
@search = Search.new(params)
end
def search_service
@search_service ||= SearchService.new(@search, current_user)
end
end
\ No newline at end of file
end
......@@ -4,22 +4,22 @@ class Search
validates_presence_of :query, :results_per_page, :order, :search_class
validates_numericality_of :results_per_page, greater_than: 0
validates :search_class, inclusion: {in: %w(LearningObject Collection User)}
validates :search_class, inclusion: { in: %w(LearningObject Collection User) }
def initialize(params={})
super(defaults.merge(params.select { |key,value| self.respond_to? key }))
def initialize(params = {})
super(defaults.merge(params.select { |key, _value| respond_to? key }))
end
def learning_object?
@search_class == "LearningObject"
search_class == 'LearningObject'
end
def collection?
@search_class == "Collection"
search_class == 'Collection'
end
def user?
@search_class == "User"
search_class == 'User'
end
private
......@@ -32,5 +32,4 @@ class Search
results_per_page: 10
}
end
end
\ No newline at end of file
end
class SearchService
attr_accessor :search
def initialize(search, user)
@search = search
@user = user
end
def fetch
validate
return search_learning_object if @search.learning_object?
return search_collection if @search.collection?
return search_user if @search.user?
end
def autocomplete
validate
params_hash = {}
get_thumbnail = nil
get_type = nil
if @search.learning_object?
params_hash = { where: {state: validate_object},
fields: ['name^10', 'description', 'author'] }
get_thumbnail = Proc.new { |obj| obj.default_thumbnail }
get_type = Proc.new { |obj| obj.object_type.try(:name) }
elsif @search.collection?
params_hash = { where: {privacy: "public"},
fields: ['name^10', 'description', 'owner'] }
get_thumbnail = Proc.new { |obj| "/assets/icons/collection" }
get_type = Proc.new { |obj| "Collection"}
else #User
params_hash = { fields: ['name'] }
get_thumbnail = Proc.new { |obj| obj.avatar.url(:thumb) }
get_type = Proc.new { |obj| "User" }
end
autocomplete_search(Object.const_get(@search.search_class), @search.query, params_hash, get_type, get_thumbnail)
module SearchService
def self.search(search, user)
model = instance(search, user)
model.search.results
end
private
def validate
raise "Invalid search" unless @search.valid?
end
def search_learning_object
LearningObject.search(@search.query, where: lo_where_hash, order: lo_order_hash(@search.order), page: @search.page, per_page: @search.results_per_page).results
end
def search_collection
Collection.search(@search.query, where: {privacy: "public"}, order: col_order_hash(@search.order), page: @search.page, per_page: @search.results_per_page).results
def self.autocomplete(search, user)
model = instance(search, user)
model.autocomplete
end
def search_user
User.search(@search.query, order: user_order_hash(@search.order), page: @search.page, per_page: @search.results_per_page).results
def self.instance(search, user)
raise 'Invalid search' unless search.valid?
"SearchService::#{search.search_class}".constantize.new(search, user)
end
def autocomplete_search(search_class, query, params_hash={}, get_type, get_thumbnail)
response = []
search_params = { limit: 10, misspellings: { below: 5 } }
objs = search_class.search(query, search_params.merge(params_hash))
objs.each do |obj|
hash = {}
hash["id"] = obj.id
hash["name"] = obj.name
hash["type"] = get_type.call(obj)
hash["thumbnail"] = get_thumbnail.call(obj)
response << hash
end
response
end
def lo_where_hash
hash = {}
hash[:tags] = @search.tags unless @search.tags.blank?
hash[:object_type] = @search.types unless @search.types.blank?
hash[:source] = @search.sources unless @search.sources.blank?
hash[:state] = validate_object
hash.blank? ? nil : hash
end
def lo_order_hash(order)
case order
when 'author'
{ author: {order: :asc, unmapped_type: :string} }
when 'publicationasc'
{ published_at: {order: :asc, unmapped_type: :timestamp} }
when 'publicationdesc'
{ published_at: {order: :desc, unmapped_type: :timestamp} }
when 'title'
{ name: {order: :asc, unmapped_type: :string} }
else
{ score: {order: :desc, unmapped_type: :integer} }
end
end
def col_order_hash(order)
case order
when 'author'
{ owner: {order: :asc, unmapped_type: :string} }
when 'publicationasc'
{ created_at: {order: :asc, unmapped_type: :timestamp} }
when 'publicationdesc'
{ created_at: {order: :desc, unmapped_type: :timestamp} }
when 'title'
{ name: {order: :asc, unmapped_type: :string} }
else
{ score: {order: :desc, unmapped_type: :integer} }
end
end
def user_order_hash(order)
if order == 'title'
{ name: {order: :asc, unmapped_type: :string} }
else
{ score: {order: :desc, unmapped_type: :integer} }
end
end
def validate_object
return 'published' unless !@user.nil? && @user.is_admin?
return ['published', 'suspended', 'draft']
end
end
\ No newline at end of file
end
module SearchService
class Collection < Model
def search
::Collection.search(@search.query, where: { privacy: 'public' }, order: order_hash, page: @search.page, per_page: @search.results_per_page)
end
def autocomplete
params = { where: { privacy: 'public' },
fields: ['name^10', 'description', 'owner'] }
result = ::Collection.search(@search.query, autocomplete_params.merge(params))
thumbnail = proc { |_obj| '/assets/icons/collection' }
type = proc { |_obj| 'Collection' }
autocomplete_render(result, type, thumbnail)
end
private
def order_hash
case @search.order
when 'author' then { owner: { order: :asc, unmapped_type: :string } }
when 'publicationasc' then { created_at: { order: :asc, unmapped_type: :timestamp } }
when 'publicationdesc' then { created_at: { order: :desc, unmapped_type: :timestamp } }
when 'title' then { name: { order: :asc, unmapped_type: :string } }
else { score: { order: :desc, unmapped_type: :integer } }
end
end
end
end
module SearchService
class LearningObject < Model
def search
::LearningObject.search(@search.query, where: where_hash, order: order_hash, page: @search.page, per_page: @search.results_per_page)
end
def autocomplete
params = { where: { state: validate_object },
fields: ['name^10', 'description', 'author'] }
result = ::LearningObject.search(@search.query, autocomplete_params.merge(params))
thumbnail = proc { |obj| obj.default_thumbnail }
type = proc { |obj| obj.object_type.try(:name) }
autocomplete_render(result, type, thumbnail)
end
private
def where_hash
hash = {}
hash[:tags] = @search.tags unless @search.tags.blank?
hash[:object_type] = @search.types unless @search.types.blank?
hash[:source] = @search.sources unless @search.sources.blank?
hash[:state] = validate_object
hash.blank? ? nil : hash
end
def order_hash
case @search.order
when 'author' then { author: { order: :asc, unmapped_type: :string } }
when 'publicationasc' then { published_at: { order: :asc, unmapped_type: :timestamp } }
when 'publicationdesc' then { published_at: { order: :desc, unmapped_type: :timestamp } }
when 'title' then { name: { order: :asc, unmapped_type: :string } }
else { score: { order: :desc, unmapped_type: :integer } }
end
end
def validate_object
return 'published' unless !@user.nil? && @user.is_admin?
%w(published suspended draft)
end
end
end
module SearchService
class Model
def initialize(search, user)
raise 'Invalid search' unless search.valid?
@search = search
@user = user
end
def search
raise 'Must implement!'
end
def autocomplete
raise 'Must implement!'
end
private
def autocomplete_params
{ limit: 10, misspellings: { below: 5 } }
end
def autocomplete_render(result, type, thumbnail)
result.map do |obj|
{
id: obj.id,
name: obj.name,
type: type.call(obj),
thumbnail: thumbnail.call(obj)
}
end
end
end
end
module SearchService
class User < Model
def search
::User.search(@search.query, order: order_hash, page: @search.page, per_page: @search.results_per_page)
end
def autocomplete
result = ::User.search(@search.query, autocomplete_params.merge(fields: ['name']))
thumbnail = proc { |obj| obj.avatar.url(:thumb) }
type = proc { |_obj| 'User' }
autocomplete_render(result, type, thumbnail)
end
private
def order_hash
return { name: { order: :asc, unmapped_type: :string } } if @search.order == 'title'
{ score: { order: :desc, unmapped_type: :integer } }
end
end
end
require 'test_helper'
class SearchServiceTest < ActiveSupport::TestCase
test 'fetch learning object with all search params' do
reindex LearningObject
service = SearchService.new(Search.new(los_complete_search), users(:john))
assert_equal [learning_objects(:search)], service.fetch
search = SearchService.search(Search.new(los_complete_search), users(:john))
assert_equal [learning_objects(:search)], search
end
test 'fetch all public collections' do
reindex Collection
service = SearchService.new(Search.new(collections_search), users(:john))
assert_equal [collections(:ufpr)], service.fetch
search = SearchService.search(Search.new(collections_search), users(:john))
assert_equal [collections(:ufpr)], search
end
test 'fetch users named john' do
reindex User
service = SearchService.new(Search.new(users_john_search), users(:john))
assert_equal [users(:john), users(:one)], service.fetch
search = SearchService.search(Search.new(users_john_search), users(:john))
assert_equal [users(:john), users(:one)], search
end
test 'autocomplete users named john' do
reindex User
service = SearchService.new(Search.new(users_john), users(:john))
assert_equal users_autocomplete_hashes([users(:john),users(:one)]), service.autocomplete
search = SearchService.autocomplete(Search.new(users_john), users(:john))
assert_equal users_autocomplete_hashes([users(:john), users(:one)]), search
end
private
def los_complete_search
default_params.merge({
:query => 'teste',
:search_class => 'LearningObject',
:tags => ['Matemática'],
:types => ['Imagem'],
:sources => ['UFPR institution']
})
default_params.merge(
query: 'teste',
search_class: 'LearningObject',
tags: ['Matemática'],
types: ['Imagem'],
sources: ['UFPR institution']
)
end
def collections_search
default_params.merge({
:search_class => 'Collection'
})
default_params.merge(search_class: 'Collection')
end
def users_john_search
default_params.merge(users_john)
end
def users_john
{
:query => 'John',
:search_class => 'User'
query: 'John',
search_class: 'User'
}
end
def default_params
{
:page => 1,
:results_per_page => 10,
:order => 'score'
page: 1,
results_per_page: 10,
order: 'score'
}
end
......@@ -72,17 +69,14 @@ class SearchServiceTest < ActiveSupport::TestCase
klass.searchkick_index.refresh
end
def users_autocomplete_hashes(users=[])
hashes = []
users.each do |user|
hash = {}
hash["id"] = user.id
hash["name"] = user.name
hash["type"] = "User"
hash["thumbnail"] = user.avatar.url(:thumb)
hashes << hash
def users_autocomplete_hashes(users = [])
users.map do |user|
{
id: user.id,
name: user.name,
type: 'User',
thumbnail: user.avatar.url(:thumb)
}
end
hashes
end
end
\ No newline at end of file
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment