<commit_before>class Rubygem < ActiveRecord::Base
  has_many :owners, :through => :ownerships, :source => :user
  has_many :ownerships, :dependent => :destroy
  has_many :subscribers, :through => :subscriptions, :source => :user
  has_many :subscriptions, :dependent => :destroy
  has_many :versions, :dependent => :destroy
  has_many :web_hooks, :dependent => :destroy
  has_one :linkset, :dependent => :destroy

  validate :ensure_name_format
  validates_presence_of :name
  validates_uniqueness_of :name

  def self.with_versions
    where("rubygems.id IN (SELECT rubygem_id FROM versions where versions.indexed IS true)")
  end

  def self.with_one_version
    select('rubygems.*').
    joins(:versions).
    group(column_names.map { |name| "rubygems.#{name}" }.join(', ')).
    having('COUNT(versions.id) = 1')
  end

  def self.name_is(name)
    where(:name => name.strip).limit(1)
  end

  def self.search(query)
    where("versions.indexed and (upper(name) like upper(:query) or upper(versions.description) like upper(:query))", {:query => "%#{query.strip}%"}).
      includes(:versions).
      order("rubygems.downloads desc")
  end

  def self.name_starts_with(letter)
    where("upper(name) like upper(?)", "#{letter}%")
  end

  def self.total_count
    with_versions.count
  end

  def self.latest(limit=5)
    with_one_version.order("created_at desc").limit(limit)
  end

  def self.downloaded(limit=5)
    with_versions.order("downloads desc").limit(limit)
  end

  def self.letter(letter)
    name_starts_with(letter).order("name asc").with_versions
  end

  def self.letterize(letter)
    letter =~ /\A[A-Za-z]\z/ ? letter.upcase : 'A'
  end
<commit_msg>Searches now handle special characters nicely<commit_after>class Rubygem < ActiveRecord::Base
  SPECIAL_CHARACTERS = ".-_"

  has_many :owners, :through => :ownerships, :source => :user
  has_many :ownerships, :dependent => :destroy
  has_many :subscribers, :through => :subscriptions, :source => :user
  has_many :subscriptions, :dependent => :destroy
  has_many :versions, :dependent => :destroy
  has_many :web_hooks, :dependent => :destroy
  has_one :linkset, :dependent => :destroy

  validate :ensure_name_format
  validates_presence_of :name
  validates_uniqueness_of :name

  def self.with_versions
    where("rubygems.id IN (SELECT rubygem_id FROM versions where versions.indexed IS true)")
  end

  def self.with_one_version
    select('rubygems.*').
    joins(:versions).
    group(column_names.map { |name| "rubygems.#{name}" }.join(', ')).
    having('COUNT(versions.id) = 1')
  end

  def self.name_is(name)
    where(:name => name.strip).limit(1)
  end

  def self.search(query)
    where("versions.indexed and (upper(name) like upper(:query) or upper(translate(name, '#{SPECIAL_CHARACTERS}', '#{' ' * SPECIAL_CHARACTERS.length}')) like upper(:query) or upper(versions.description) like upper(:query))", {:query => "%#{query.strip}%"}).
      includes(:versions).
      order("rubygems.downloads desc")
  end

  def self.name_starts_with(letter)
    where("upper(name) like upper(?)", "#{letter}%")
  end

  def self.total_count
    with_versions.count
  end

  def self.latest(limit=5)
    with_one_version.order("created_at desc").limit(limit)
  end

  def self.downloaded(limit=5)
    with_versions.order("downloads desc").limit(limit)
  end

  def self.letter(letter)
    name_starts_with(letter).order("name asc").with_versions
  end

  def self.letterize(letter)
    letter =~ /\A[A-Za-z]\z/ ? letter.upcase : 'A'
  end

{'fraction_non_alphanumeric': 0.14521640091116172, 'fraction_numerical': 0.002277904328018223, 'mean_word_length': 4.371559633027523, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3266940', 'n_tokens_mistral': 1211, 'n_tokens_neox': 1178, 'n_words': 252}