Wenn Sie in ActiveRecord eine Zeichenfolge in eine Spalte vom Typ Datum oder Ganzzahl einfügen, wird diese automatisch in diesen Spaltentyp konvertiert.
Wenn Sie beispielsweise die folgende Benutzertabelle haben: (Created_at und aktualisierte_at werden der Einfachheit halber weggelassen.)
create_table "users", force: :cascade do |t|
t.string "name"
t.integer "age"
end
Versuchen wir, verschiedene Werte über die Rails-Konsole einzugeben.
irb (main): 001: 0> User.new (Name: "Taro", Alter: 21) Versuchen Sie, eine Nummer in #age einzugeben
=> # <Benutzername: "Taro", Alter: 21>
irb (main): 002: 0> User.new (Name: "Taro", Alter: "21") Versuchen Sie, eine Zeichenfolge in #age einzufügen
=> # <Benutzername: "Taro", Alter: 21>
irb (main): 003: 0> User.new (Name: "Taro", Alter: "21") Versuchen Sie, eine Zeichenfolge in #age einzufügen (1 ist eine Zahl in voller Breite).
=> # <Benutzername: "Taro", Alter: 2>
Der erste ist ein numerischer Wert. Da es sich um einen numerischen Wert handelt, kann er unverändert eingegeben werden.
Der zweite ist eine Zeichenfolge. Die Zeichenfolge "21" wurde in die Nummer 21 konvertiert. Wunderbar.
Wie wäre es mit dem dritten, der 1 Teil von "21" ist eine Zahl in voller Breite. Es ist Alter geworden: 2. Es ist völlig anders als 21.
Übrigens, selbst wenn Sie "2 1" (mit einem Leerzeichen dazwischen) oder "2 a" (mit einem anderen Zeichen als einer Zahl) verwenden, ist es Alter: 2.
Angenommen, Sie versuchen, eine nicht numerische Eingabe abzuspielen und die folgende Validierung anzuwenden.
validates :age, format: { with: /\A[0-9]+\z/}
In diesem Fall wird, wenn der Benutzer "2 1", "2 a" usw. eingibt, die Validierung auf das 2. Lebensjahr angewendet und als korrekte Daten gespeichert.
Die Lösung besteht darin, _before_type_cast zu age hinzuzufügen, um den vom Benutzer eingegebenen Wert anstelle des Werts nach der Konvertierung des Typs zu überprüfen. [* Referenz "before_type_cast with Rails / Validates"](https://dora.bk.tsukuba.ac.jp/~takeuchi/?%E3%82%BD%E3%83%95%E3%83%88%E3 % 82% A6% E3% 82% A7% E3% 82% A2% 2Frails% 2Fvalidates% E3% 81% A7before_type_cast)
validates :age_before_type_cast, format: { with: /\A[0-9]+\z/ }, presence: true
Zusätzlich zur Validierung ist _before_type_cast auch nützlich, wenn Sie alphanumerische Zeichen in einer Zeichenfolge von voller Breite in halbe Breite konvertieren möchten oder wenn Sie nach dem Entfernen von Leerzeichen speichern möchten.
Im folgenden Code wird beispielsweise ein Edelstein namens Moji verwendet, um von voller Breite in halbe Breite zu konvertieren.
Dieses Mal verwende ich _before_type_cast, weil ich die Eingabe, die eine Mischung aus voller Breite und halber Breite ist, wie "21" (1 ist volle Breite) des Benutzers, vor der Validierung auf halbe Breite ausrichten möchte.
Nachdem die Zeichenfolge so empfangen wurde, wie sie vom Benutzer mit age_before_type_cast eingegeben wurde, und konvertiert wurde, wird die konvertierte Zeichenfolge in age gesetzt.
validates :age_before_type_cast, format: { with: /\A[0-9]+\z/ }, presence: true
before_validation do
string = self.send(:age_before_type_cast)
string = Moji.normalize_zen_han(string)
send(:write_attribute, :age, string)
end
Erstens ist der Unterschied zwischen normalen Attributen und Attributen mit _before_type_cast. Der Wert kann nicht mit [: 〇〇_before_type_cast] erhalten werden. Speziell
irb (main): 001: 0> user = User.new (Name: "Taro", Alter: "21")
irb(main):002:0> user.age
=> 21
irb(main):003:0> user.age_before_typecast
=> "21"
irb(main):004:0> user[:age]
=> 21
irb(main):005:0> user[:age_before_typecast]
=> nil
Sie können den Wert mit user.age_before_type_cast erhalten. Wenn ich versuche, den Wert mit user [: age_before_type_cast] abzurufen, wird nil zurückgegeben.
irb(main):001:0> user.age = 21
=> 21
irb(main):002:0> user.age_before_type_cast = 21
=> #NoMethodError tritt auf.
Da _before_type_cast zum Überprüfen der Eingabe vor der Typkonvertierung in das Alter dient, ist es natürlich nicht möglich, sich selbst zu aktualisieren.
Wenn Sie speichern, sind 〇〇 und 〇〇_before_type_cast identisch. Speziell,
irb (main): 001: 0> user = User.new (Name: "Taro", Alter: "21")
irb(main):002:0> user.save
irb(main):003:0> user.age_before_typecast
=> 21
Die Nummer 21 wird anstelle der Zeichenfolge "21" zurückgegeben.
Seien Sie beim Implementieren oder Testen aufgrund der oben genannten Eigenschaften vorsichtig!
[before_type_cast with Rails / Validates](https://dora.bk.tsukuba.ac.jp/~takeuchi/?%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6 % E3% 82% A7% E3% 82% A2% 2Frails% 2Fvalidates% E3% 81% A7before_type_cast)
Recommended Posts