Frage

Ich habe ein ActiveRecord Modell, Foo, das eine name Feld hat. Ich möchte Benutzer nach dem Namen suchen zu können, aber ich würde die Suche gerne Fall und keine Akzente zu ignorieren. So, ich bin die Speicherung auch ein canonical_name Feld, gegen die suchen:

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

Ich muss in der „hier etwas“ füllen, die akzentuierte Zeichen zu ersetzen. Gibt es etwas Schöneres als

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

Und was das betrifft, da ich nicht auf Rubin bin 1.9, kann ich nicht diese Unicode-Literale in meinem Code setzen. Die tatsächlichen reguläre Ausdrücke aussehen wird viel hässlicher.

War es hilfreich?

Lösung

Rails hat bereits einen eingebauten für Normalisieren, man muss nur so Ihre Zeichenfolge zu normalisieren KD zu bilden, und dann entfernen Sie die anderen Zeichen (das heißt Akzentzeichen) wie folgt aus:

>> "àáâãäå".mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n,'').downcase.to_s
=> "aaaaaa"

Andere Tipps

ActiveSupport::Inflector.transliterate (erfordert Rails 2.2.1+ und Ruby 1.9 bzw. 1.8.7)

Beispiel:

>> ActiveSupport::Inflector.transliterate("àáâãäå").to_s => "aaaaaa"

Noch besser wäre es ist I18n zu verwenden:

1.9.3-p392 :001 > require "i18n"
 => false
1.9.3-p392 :002 > I18n.transliterate("Olá Mundo!")
 => "Ola Mundo!"

Ich habe viele dieser Ansätze versucht, aber sie waren nicht eine oder mehrere dieser Anforderungen zu erreichen:

  • Respect Räume
  • Respekt 'ñ' Zeichen
  • Respekt Fall (ich weiß, ist keine Voraussetzung für die ursprüngliche Frage ist aber nicht schwierig, eine Zeichenfolge lowcase bewegen)

Wird dies:

# coding: utf-8
string.tr(
  "ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž",
  "AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz"
)

- http: //blog.slashpoundbang.com/post/12938588984/remove-all-accents-and-diacritics-from-string-in-ruby

Sie haben ein wenig den Charakter Liste ändern ‚ñ‘ Charakter zu respektieren, sondern ist eine einfache Aufgabe.

Meine Antwort: die String # parametrieren Methode:

"Le cœur de la crémiére".parameterize
=> "le-coeur-de-la-cremiere"

Für Nicht-Rails-Programme:

Installieren Sie Active: gem install activesupport dann:

require 'active_support/inflector'
"a&]'s--3\014\xC2àáâã3D".parameterize
# => "a-s-3-3d"

Ich denke, dass Sie vielleicht nicht wirklich das, was diesen Weg zu gehen. Wenn Sie einen Markt zu entwickeln, die diese Art von Briefen Benutzer hat wahrscheinlich denken, dass Sie sind eine Art ... pip . Da ‚A‘ ist nicht einmal in der Nähe ‚a‘ in jeder Bedeutung für einen Benutzer. Nehmen Sie einen anderen Weg und informieren Sie sich über in einer Nicht-Ascii-Art und Weise zu suchen. Dies ist nur einer der Fälle, jemand erfunden Unicode und Sortierungs .

Ein sehr spät PS :

http://www.w3.org/International/wiki/Case_folding http://www.w3.org/TR/charmod-norm/# sec-WhyNormalization

Außerdem habe ich keine ide Art und Weise die Verbindung zur Sortierung zu einer Msdn Seite gehen, aber ich lasse es dort. Es hätte http://www.unicode.org/reports/tr10/

Zerlege die Zeichenfolge und entfernen nicht-spacing Markierungen von ihm.

irb -ractive_support/all
> "àáâãäå".mb_chars.normalize(:kd).gsub(/\p{Mn}/, '')
aaaaaa

Sie müssen unter Umständen auch dies in einer .rb-Datei verwendet, wenn.

# coding: utf-8

das normalize(:kd) Teil spaltet hier aus diakritische Zeichen, wenn möglich (zB: die „n mit tilda“ einzelnes Zeichen in einem n durch eine Kombination von diakritischen tilda Zeichen folgt aufgeteilt wird), und der gsub Teil entfernt dann alle diakritischen Zeichen

Dies setzt voraus, Sie Rails verwenden.

"anything".parameterize.underscore.humanize.downcase

Ihre Anforderungen gegeben, das wahrscheinlich ist, was ich tun würde ... Ich denke, es ist ordentlich, einfach und wird in zukünftigen Versionen von Rails und Ruby auf dem Laufenden bleiben.

Update: dgilperez wies darauf hin, dass parameterize ein Trenn Argument, so "anything".parameterize(" ") (veraltet) oder "anything".parameterize(separator: " ") kürzer und saubere

.

Konvertieren Sie den Text zu Normalisierungsform D, entfernen Sie alle Codepoints mit Unicode-Kategorie nicht Abstand Zeichen (Mn), und wandeln es wieder zu einer Normalisierung Form C. Dadurch werden alle diakritischen Zeichen abzustreifen, und Ihr Problem ist auf einen Fall unempfindlich Suche reduziert.

Siehe http://www.siao2.com/2005/02/ 19 / 376617.aspx und http: //www.siao2. com / 2007/05/14 / 2629747.aspx .

Der Schlüssel ist, zwei Spalten in der Datenbank zu verwenden: canonical_text und original_text. Verwenden Sie original_text für die Anzeige und canonical_text für die Suche. So, wenn ein Nutzer nach „Visuelle Cafe“, sie sieht den „Visuelles Café“ Ergebnis. Wenn sie wirklich will ein anderes Element "von Visual Cafe" genannt, es separat gespeichert werden kann.

Um die canonical_text Zeichen in einer Ruby 1.8 Quelldatei, so etwas wie folgt aus:

register_replacement([0x008A].pack('U'), 'S')

Sie wollen wahrscheinlich Unicode Zersetzung ( "NFD"). Nach dem String zersetzen, filtern, dass nur etwas aus nicht in [A-Za-z]. æ zersetzen ã "ae", zu "a ~." (etwa - die diakritische wird ein separates Zeichen werden), so dass die Filterung läßt eine vernünftige Annäherung

Für alle, die dies lesen wollen alle Nicht-ASCII-Zeichen abzustreifen diese könnte sein, nützlich, ich das erste Beispiel erfolgreich eingesetzt.

Ich hatte Probleme bekommen die foo.mb_chars.normalize (: kd). .Gsub (/ [^ \ x00- \ x7F] / n, '') downcase.to_s Lösung zu arbeiten. Ich bin nicht Rails und es gab einige Konflikte mit meinem Active / ruby-Versionen, die ich nicht auf den Grund bekommen.

Mit dem rubin unf Juwel scheint einen guten Ersatz zu sein:

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

Soweit ich sagen kann, dies macht das Gleiche wie .mb_chars.normalize (: kd). Ist das richtig? Dank!

Wenn Sie PostgreSQL verwenden => 9.4 als DB-Adapter, vielleicht könnten Sie in einer Migration hinzufügen es ist "unaccent" -Erweiterung dass ich denke, das tut, was Sie wollen, wie folgt aus:

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

Um zu testen, in der Konsole:

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

Hinweis gibt es Groß- und Kleinschreibung bis jetzt.

Dann ist es vielleicht in einem Bereich verwenden, wie:

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

Der iLike Operator macht die Suche Groß- und Kleinschreibung. Es ist ein weiterer Ansatz, mit CITEXT Datentyp. Hier ist eine Diskussion über diese beiden Ansätze. Beachten Sie auch, dass die Verwendung von PosgreSQL der unteren () Funktion wird nicht empfohlen .

Dies wird Ihnen einige DB Platz sparen, da Sie nicht mehr das cannonical_name Feld benötigen, und vielleicht Ihr Modell einfacher, auf Kosten von einigen zusätzlichen Verarbeitung in jeder Abfrage in einer Menge machen, abhängig davon, ob Sie mit iLike oder CITEXT und Ihre Datenmenge.

Wenn Sie MySQL verwenden vielleicht können Sie diese einfache Lösung verwenden, aber ich habe nicht getestet.

lol .. ich dies nur tryed .. und es funktioniert .. iam noch nicht ganz sicher, warum .. aber wenn ich diese 4 Zeilen Code:

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

Es entfernt automatisch alle Akzente aus Dateinamen .. die i (Akzent aus Dateinamen und Umbenennen von ihnen als) zu entfernen versuchen hoffen, dass es geholfen:)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top