Как заменить акцентированные латинские символы в Ruby? - PullRequest
69 голосов
/ 22 октября 2008

У меня есть модель ActiveRecord, Foo, которая имеет поле name. Я бы хотел, чтобы пользователи могли выполнять поиск по имени, но я бы хотел, чтобы поиск игнорировал регистр и любые акценты. Таким образом, я также храню поле canonical_name для поиска:

class Foo
  validates_presence_of :name

  before_validate :set_canonical_name

  private

  def set_canonical_name
    self.canonical_name ||= canonicalize(self.name) if self.name
  end

  def canonicalize(x)
    x.downcase.  # something here
  end
end

Мне нужно заполнить «что-то здесь», чтобы заменить акцентированные символы. Есть ли что-нибудь лучше, чем

x.downcase.gsub(/[àáâãäå]/,'a').gsub(/æ/,'ae').gsub(/ç/, 'c').gsub(/[èéêë]/,'e')....

И, кстати, поскольку я не на Ruby 1.9, я не могу вставить эти литералы Unicode в мой код. Фактические регулярные выражения будут выглядеть намного ужаснее.

Ответы [ 16 ]

2 голосов
/ 22 октября 2008

Вы, вероятно, хотите декомпозицию Unicode ("NFD"). После разложения строки просто отфильтруйте все, что не в [A-Za-z]. æ разложится на «ae», ã на «a ~» (примерно - диакритический знак станет отдельным символом), поэтому фильтрация оставляет разумное приближение.

1 голос
/ 29 августа 2010

Для тех, кто читает это и хочет убрать все символы, не относящиеся к ascii это может быть полезно, я успешно использовал первый пример.

1 голос
/ 22 октября 2008

Iconv:

http://groups.google.com/group/ruby-talk-google/browse_frm/thread/8064dcac15d688ce?

=============

модуль Perl, который я не могу понять:

http://www.ahinea.com/en/tech/accented-translate.html

============

Грубая сила (есть много тварей!:

http://projects.jkraemer.net/acts_as_ferret/wiki#UTF-8support

http://snippets.dzone.com/posts/show/2384

0 голосов
/ 09 декабря 2018

Если вы используете PostgreSQL => 9.4 в качестве адаптера БД, может быть, вы могли бы добавить в миграцию это "unaccent" расширение , которое, я думаю, делает то, что вы хотите, вот так :

def self.up
   enable_extension "unaccent" # No falla si ya existe
end

Для проверки в консоли:

2.3.1 :045 > ActiveRecord::Base.connection.execute("SELECT unaccent('unaccent', 'àáâãäåÁÄ')").first
 => {"unaccent"=>"aaaaaaAA"}

Обратите внимание, что до сих пор чувствительны к регистру.

Тогда, возможно, используйте его в области видимости, например:

scope :with_canonical_name, -> (name) {
   where("unaccent(foos.name) iLIKE unaccent('#{name}')")
}

Оператор iLIKE делает регистр поиска нечувствительным. Существует другой подход, использующий тип данных citext . Здесь - обсуждение этих двух подходов. Также обратите внимание, что не рекомендуется использовать нижнюю () функцию PosgreSQL .

Это сэкономит вам некоторое пространство БД, поскольку вам больше не потребуется поле cannonical_name и, возможно, упростит вашу модель за счет некоторой дополнительной обработки в каждом запросе в размере, зависящем от того, используете ли вы iLIKE или Цитата, и ваш набор данных.

Если вы используете MySQL , возможно, вы можете использовать это простое решение , но я его не проверял.

0 голосов
/ 19 сентября 2012

У меня были проблемы с получением решения foo.mb_chars.normalize (: kd) .gsub (/ [^ \ x00- \ x7F] / n, ''). Downcase.to_s. Я не использую Rails, и у меня были некоторые конфликты с моими версиями activesupport / ruby, из-за которых я не смог добраться до сути.

Использование драгоценного камня ruby-unf представляется хорошей заменой:

require 'unf'
foo.to_nfd.gsub(/[^\x00-\x7F]/n,'').downcase

Насколько я могу судить, это делает то же самое, что и .mb_chars.normalize (: kd). Это правильно? Спасибо!

0 голосов
/ 29 марта 2009

смеется .. я только что попробовал это .. и это работает .. я все еще не совсем уверен, почему .. но когда я использую это 4 строки кода:

  • str = str.gsub (/ [^ a-zA-Z0-9] /, "")
  • str = str.gsub (/ [] + /, "")
  • str = str.gsub (/ /, "-")
  • str = str.downcase

он автоматически удаляет любой акцент из имен файлов .. который я пытался удалить (акцент из имен файлов и переименовывает их, чем) надеюсь, что это помогло:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...