<commit_before># frozen_string_literal: true
class SearchController < ApplicationController
  include TopicsHelper
  include MapsHelper
  include UsersHelper
  include SynapsesHelper

  before_action :authorize_search
  after_action :verify_authorized
  after_action :verify_policy_scoped, only: [:maps, :mappers, :synapses, :topics]

  # get /search/topics?term=SOMETERM
  def topics
    term = params[:term]
    user = params[:user] ? params[:user] : false

    if term && !term.empty? && term.downcase[0..3] != 'map:' && term.downcase[0..6] != 'mapper:' && !term.casecmp('topic:').zero?

      # remove "topic:" if appended at beginning
      term = term[6..-1] if term.downcase[0..5] == 'topic:'

      # if desc: search desc instead
      desc = false
      if term.downcase[0..4] == 'desc:'
        term = term[5..-1]
        desc = true
      end

      # if link: search link instead
      link = false
      if term.downcase[0..4] == 'link:'
        term = term[5..-1]
        link = true
      end

      # check whether there's a filter by metacode as part of the query
      filterByMetacode = false
      Metacode.all.each do |m|
        lOne = m.name.length + 1
        lTwo = m.name.length

        if term.downcase[0..lTwo] == m.name.downcase + ':'
          term = term[lOne..-1]
          filterByMetacode = m
        end
      end

      search = '%' + term.downcase + '%'
      builder = policy_scope(Topic)

      if filterByMetacode
        if term == ''
          builder = builder.none
        else
          builder = builder.where('LOWER("name") like ? OR
                                   LOWER("desc") like ? OR
                                   LOWER("link") like ?', search, search, search)
          builder = builder.where(metacode_id: filterByMetacode.id)
        end
      elsif desc
        builder = builder.where('LOWER("desc") like ?', search)
      elsif link
        builder = builder.where('LOWER("link") like ?', search)
      else # regular case, just search the name
        builder = builder.where('LOWER("name") like ? OR
                                 LOWER("desc") like ? OR
                                 LOWER("link") like ?', search, search, search)
      end

      builder = builder.where(user: user) if user
      @topics = builder.order(:name)
    else
      @topics = []
    end

    render json: autocomplete_array_json(@topics).to_json
  end

  # get /search/maps?term=SOMETERM
  def maps
    term = params[:term]
    user = params[:user] ? params[:user] : nil

    if term && !term.empty? && term.downcase[0..5] != 'topic:' && term.downcase[0..6] != 'mapper:' && !term.casecmp('map:').zero?

      # remove "map:" if appended at beginning
      term = term[4..-1] if term.downcase[0..3] == 'map:'

      # if desc: search desc instead
      desc = false
      if term.downcase[0..4] == 'desc:'
        term = term[5..-1]
        desc = true
      end

      search = '%' + term.downcase + '%'
      builder = policy_scope(Map)

      builder = if desc
                  builder.where('LOWER("desc") like ?', search)
                else
                  builder.where('LOWER("name") like ?', search)
                end
      builder = builder.where(user: user) if user
      @maps = builder.order(:name)
    else
      @maps = []
    end

    render json: autocomplete_map_array_json(@maps).to_json
  end

  # get /search/mappers?term=SOMETERM
  def mappers
    term = params[:term]
    if term && !term.empty? && term.downcase[0..3] != 'map:' && term.downcase[0..5] != 'topic:' && !term.casecmp('mapper:').zero?

      # remove "mapper:" if appended at beginning
      term = term[7..-1] if term.downcase[0..6] == 'mapper:'
      search = term.downcase + '%'

      skip_policy_scope # TODO: builder = policy_scope(User)
      builder = User.where('LOWER("name") like ?', search)
      @mappers = builder.order(:name)
    else
      @mappers = []
    end
    render json: autocomplete_user_array_json(@mappers).to_json
  end

  # get /search/synapses?term=SOMETERM OR
  # get /search/synapses?topic1id=SOMEID&topic2id=SOMEID
  def synapses
    term = params[:term]
    topic1id = params[:topic1id]
    topic2id = params[:topic2id]

    if term && !term.empty?
      @synapses = policy_scope(Synapse).where('LOWER("desc") like ?', '%' + term.downcase + '%').order('"desc"')

      @synapses = @synapses.uniq(&:desc)
    elsif topic1id && !topic1id.empty?
      @one = policy_scope(Synapse).where(topic1_id: topic1id, topic2_id: topic2id)
      @two = policy_scope(Synapse).where(topic2_id: topic1id, topic1_id: topic2id)
      @synapses = @one + @two
      @synapses.sort! { |s1, s2| s1.desc <=> s2.desc }.to_a
    else
      @synapses = []
    end

    # limit to 5 results
    @synapses = @synapses.to_a.slice(0, 5)

    render json: autocomplete_synapse_array_json(@synapses).to_json
  end

  private

  def authorize_search
    authorize :Search
  end
end<commit_msg>strip whitespace from search terms (#919)<commit_after># frozen_string_literal: true
class SearchController < ApplicationController
  include TopicsHelper
  include MapsHelper
  include UsersHelper
  include SynapsesHelper

  before_action :authorize_search
  after_action :verify_authorized
  after_action :verify_policy_scoped, only: [:maps, :mappers, :synapses, :topics]

  # get /search/topics?term=SOMETERM
  def topics
    term = params[:term]
    user = params[:user] ? params[:user] : false

    if term && !term.empty? && term.downcase[0..3] != 'map:' && term.downcase[0..6] != 'mapper:' && !term.casecmp('topic:').zero?

      # remove "topic:" if appended at beginning
      term = term[6..-1] if term.downcase[0..5] == 'topic:'

      # if desc: search desc instead
      desc = false
      if term.downcase[0..4] == 'desc:'
        term = term[5..-1]
        desc = true
      end

      # if link: search link instead
      link = false
      if term.downcase[0..4] == 'link:'
        term = term[5..-1]
        link = true
      end

      # check whether there's a filter by metacode as part of the query
      filterByMetacode = false
      Metacode.all.each do |m|
        lOne = m.name.length + 1
        lTwo = m.name.length

        if term.downcase[0..lTwo] == m.name.downcase + ':'
          term = term[lOne..-1]
          filterByMetacode = m
        end
      end

      search = '%' + term.downcase.strip + '%'
      builder = policy_scope(Topic)

      if filterByMetacode
        if term == ''
          builder = builder.none
        else
          builder = builder.where('LOWER("name") like ? OR
                                   LOWER("desc") like ? OR
                                   LOWER("link") like ?', search, search, search)
          builder = builder.where(metacode_id: filterByMetacode.id)
        end
      elsif desc
        builder = builder.where('LOWER("desc") like ?', search)
      elsif link
        builder = builder.where('LOWER("link") like ?', search)
      else # regular case, just search the name
        builder = builder.where('LOWER("name") like ? OR
                                 LOWER("desc") like ? OR
                                 LOWER("link") like ?', search, search, search)
      end

      builder = builder.where(user: user) if user
      @topics = builder.order(:name)
    else
      @topics = []
    end

    render json: autocomplete_array_json(@topics).to_json
  end

  # get /search/maps?term=SOMETERM
  def maps
    term = params[:term]
    user = params[:user] ? params[:user] : nil

    if term && !term.empty? && term.downcase[0..5] != 'topic:' && term.downcase[0..6] != 'mapper:' && !term.casecmp('map:').zero?

      # remove "map:" if appended at beginning
      term = term[4..-1] if term.downcase[0..3] == 'map:'

      # if desc: search desc instead
      desc = false
      if term.downcase[0..4] == 'desc:'
        term = term[5..-1]
        desc = true
      end

      search = '%' + term.downcase.strip + '%'
      builder = policy_scope(Map)

      builder = if desc
                  builder.where('LOWER("desc") like ?', search)
                else
                  builder.where('LOWER("name") like ?', search)
                end
      builder = builder.where(user: user) if user
      @maps = builder.order(:name)
    else
      @maps = []
    end

    render json: autocomplete_map_array_json(@maps).to_json
  end

  # get /search/mappers?term=SOMETERM
  def mappers
    term = params[:term]
    if term && !term.empty? && term.downcase[0..3] != 'map:' && term.downcase[0..5] != 'topic:' && !term.casecmp('mapper:').zero?

      # remove "mapper:" if appended at beginning
      term = term[7..-1] if term.downcase[0..6] == 'mapper:'
      search = term.downcase.strip + '%'

      skip_policy_scope # TODO: builder = policy_scope(User)
      builder = User.where('LOWER("name") like ?', search)
      @mappers = builder.order(:name)
    else
      @mappers = []
    end
    render json: autocomplete_user_array_json(@mappers).to_json
  end

  # get /search/synapses?term=SOMETERM OR
  # get /search/synapses?topic1id=SOMEID&topic2id=SOMEID
  def synapses
    term = params[:term]
    topic1id = params[:topic1id]
    topic2id = params[:topic2id]

    if term && !term.empty?
      @synapses = policy_scope(Synapse).where('LOWER("desc") like ?', '%' + term.downcase.strip + '%').order('"desc"')

      @synapses = @synapses.uniq(&:desc)
    elsif topic1id && !topic1id.empty?
      @one = policy_scope(Synapse).where(topic1_id: topic1id, topic2_id: topic2id)
      @two = policy_scope(Synapse).where(topic2_id: topic1id, topic1_id: topic2id)
      @synapses = @one + @two
      @synapses.sort! { |s1, s2| s1.desc <=> s2.desc }.to_a
    else
      @synapses = []
    end

    # limit to 5 results
    @synapses = @synapses.to_a.slice(0, 5)

    render json: autocomplete_synapse_array_json(@synapses).to_json
  end

  private

  def authorize_search
    authorize :Search
  end
end
{'fraction_non_alphanumeric': 0.13829572925060435, 'fraction_numerical': 0.012792103142626915, 'mean_word_length': 2.298671096345515, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3501373', 'n_tokens_mistral': 3316, 'n_tokens_neox': 3190, 'n_words': 746}