Mein Produktmodell enthält einige Artikel
Product.first
=> #<Product id: 10, name: "Blue jeans" >
Ich importiere jetzt einige Produktparameter aus einem anderen Datensatz, aber es gibt Inkonsistenzen in der Schreibweise der Namen. Zum Beispiel könnte im anderen Datensatz Blue jeans
geschrieben werden Blue Jeans
.
Ich wollte Product.find_or_create_by_name("Blue Jeans")
, aber dadurch entsteht ein neues Produkt, das fast identisch mit dem ersten ist. Was sind meine Optionen, wenn ich den Namen in Kleinbuchstaben suchen und vergleichen möchte?
Leistungsprobleme sind hier nicht wirklich wichtig: Es gibt nur 100-200 Produkte, und ich möchte dies als Migration ausführen, die die Daten importiert.
Irgendwelche Ideen?
ruby-on-rails
activerecord
case-insensitive
Jesper Rønn-Jensen
quelle
quelle
"$##"
und'$##'
. Der erste wird interpoliert (doppelte Anführungszeichen). Der zweite ist nicht. Benutzereingaben werden niemals interpoliert.find(:first)
veraltet ist und die Option jetzt verwendet werden kann#first
. SoProduct.first(conditions: [ "lower(name) = ?", name.downcase ])
model = Product.where('lower(name) = ?', name.downcase).first_or_create
after_create
Rückruf imProduct
Modell und innerhalb des Rückrufs haben wir einewhere
Klausel, zproducts = Product.where(country: 'us')
. In diesem Fall werden diewhere
Klauseln verkettet, wenn Rückrufe im Kontext des Bereichs ausgeführt werden. Nur zur Info.Dies ist eine vollständige Einrichtung in Rails, als meine eigene Referenz. Ich bin froh, wenn es dir auch hilft.
die Abfrage:
der Validator:
der Index (Antwort vom eindeutigen Index ohne Berücksichtigung der Groß- und Kleinschreibung in Rails / ActiveRecord? ):
Ich wünschte, es gäbe eine schönere Möglichkeit, die erste und die letzte zu machen, aber andererseits sind Rails und ActiveRecord Open Source. Wir sollten uns nicht beschweren - wir können es selbst implementieren und Pull-Anfragen senden.
quelle
find(:first, ...)
jetzt veraltet ist, denke ich, dass dies die richtigste Antwort ist.Product.where("lower(name) = ?", name).first
Wenn Sie Postegres and Rails 4+ verwenden, haben Sie die Möglichkeit, den Spaltentyp CITEXT zu verwenden, der Abfragen ohne Berücksichtigung der Groß- und Kleinschreibung ermöglicht, ohne die Abfragelogik ausschreiben zu müssen.
Die Migration:
Und um es zu testen, sollten Sie Folgendes erwarten:
quelle
Möglicherweise möchten Sie Folgendes verwenden:
Bitte beachten Sie, dass die Einstellung standardmäßig lautet: case_sensitive => false, sodass Sie diese Option nicht einmal schreiben müssen, wenn Sie keine anderen Methoden geändert haben.
Weitere Informationen finden Sie unter: http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#method-i-validates_uniqueness_of
quelle
In postgres:
quelle
Mehrere Kommentare beziehen sich auf Arel, ohne ein Beispiel anzugeben.
Hier ist ein Arel-Beispiel für eine Suche ohne Berücksichtigung der Groß- und Kleinschreibung:
Der Vorteil dieser Art von Lösung besteht darin, dass sie datenbankunabhängig ist - sie verwendet die richtigen SQL-Befehle für Ihren aktuellen Adapter (
matches
wirdILIKE
für Postgres undLIKE
für alles andere verwendet).quelle
Zitat aus der SQLite-Dokumentation :
... was ich nicht wusste. Aber es funktioniert:
Sie könnten also so etwas tun:
Nicht
#find_or_create
, ich weiß, und es ist vielleicht nicht sehr datenbankübergreifend, aber einen Blick wert?quelle
Ein anderer Ansatz, den niemand erwähnt hat, ist das Hinzufügen von Findern ohne Berücksichtigung der Groß- und Kleinschreibung zu ActiveRecord :: Base. Details finden Sie hier . Der Vorteil dieses Ansatzes besteht darin, dass Sie nicht jedes Modell ändern müssen und die
lower()
Klausel nicht zu allen Abfragen hinzufügen müssen , bei denen die Groß- und Kleinschreibung nicht berücksichtigt wird. Stattdessen verwenden Sie einfach eine andere Finder-Methode.quelle
Groß- und Kleinbuchstaben unterscheiden sich nur um ein Bit. Der effizienteste Weg, sie zu durchsuchen, besteht darin, dieses Bit zu ignorieren, nicht das untere oder obere zu konvertieren usw. Siehe Schlüsselwörter
COLLATION
für MSSQL, prüfen,NLS_SORT=BINARY_CI
ob Oracle verwendet wird usw.quelle
Find_or_create ist jetzt veraltet. Sie sollten stattdessen eine AR-Beziehung plus first_or_create verwenden, wie folgt:
Dadurch wird das erste übereinstimmende Objekt zurückgegeben oder eines für Sie erstellt, falls keines vorhanden ist.
quelle
Bei Rails ist die Suche ohne Berücksichtigung der Groß- und Kleinschreibung integriert. Es berücksichtigt Unterschiede bei der Datenbankimplementierung. Verwenden Sie entweder die integrierte Arel-Bibliothek oder ein Juwel wie Squeel .
quelle
Hier gibt es viele gute Antworten, insbesondere bei @ oma. Sie können jedoch auch versuchen, eine benutzerdefinierte Spaltenserialisierung zu verwenden. Wenn es Ihnen nichts ausmacht, dass alles in Ihrer Datenbank in Kleinbuchstaben gespeichert wird, können Sie Folgendes erstellen:
Dann in Ihrem Modell:
Der Vorteil dieses Ansatzes besteht darin, dass Sie weiterhin alle regulären Finder (einschließlich
find_or_create_by
) verwenden können, ohne benutzerdefinierte Bereiche, Funktionen oder Funktionen zu verwendenlower(name) = ?
Abfragen zu verwenden.Der Nachteil ist, dass Sie Gehäuseinformationen in der Datenbank verlieren.
quelle
Ähnlich wie Andrews, der # 1 ist:
Etwas, das für mich funktioniert hat, ist:
Dadurch entfällt die Notwendigkeit, eine
#where
und#first
dieselbe Abfrage durchzuführen. Hoffe das hilft!quelle
Sie können auch Bereiche wie diesen unten verwenden und sie in ein Anliegen aufnehmen und in Modelle aufnehmen, die Sie möglicherweise benötigen:
scope :ci_find, lambda { |column, value| where("lower(#{column}) = ?", value.downcase).first }
Dann verwenden Sie wie folgt:
Model.ci_find('column', 'value')
quelle
Angenommen, Sie verwenden MySQL, können Sie Felder verwenden, bei denen die Groß- und Kleinschreibung nicht berücksichtigt wird: http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html
quelle
quelle
TypeError: Cannot visit Regexp
Einige Leute zeigen mit LIKE oder ILIKE, aber diese erlauben Regex-Suchen. Außerdem müssen Sie in Ruby kein Downcase erstellen. Sie können die Datenbank dies für Sie tun lassen. Ich denke, es kann schneller sein. Auch
first_or_create
kann nach verwendet werdenwhere
.quelle
Eine Alternative kann sein
quelle
Bisher habe ich mit Ruby eine Lösung gefunden. Fügen Sie dies in das Produktmodell ein:
Dies gibt mir das erste Produkt, bei dem die Namen übereinstimmen. Oder null.
quelle