1 Patikrinimo apžvalga
Štai labai paprasto patikrinimo pavyzdys:
class Person < ApplicationRecord
validates :name, presence: true
end
irb> Person.create(name: "John Doe").valid?
=> true
irb> Person.create(name: nil).valid?
=> false
Kaip matote, mūsų patikrinimas leidžia mums sužinoti, kad mūsų Person
objektas nėra galiojantis be name
atributo. Antras Person
objektas nebus išsaugotas į duomenų bazę.
Prieš pradedant detaliau nagrinėti, kalbėkime apie tai, kaip patikrinimai telpa į jūsų programos bendrą vaizdą.
1.1 Kodėl naudoti patikrinimus?
Patikrinimai naudojami tam, kad būtų užtikrinta, jog į jūsų duomenų bazę būtų išsaugomi tik galiojantys duomenys. Pavyzdžiui, jūsų programai gali būti svarbu užtikrinti, kad kiekvienas vartotojas pateiktų galiojantį el. pašto adresą ir pašto adresą. Modelio lygio patikrinimai yra geriausias būdas užtikrinti, kad tik galiojantys duomenys būtų išsaugomi į jūsų duomenų bazę. Jie yra duomenų bazės nepriklausomi, negali būti apeiti naudotojų ir patogūs testuoti bei palaikyti. „Rails“ teikia įdiegtus pagalbinius įrankius bendriems poreikiams ir leidžia kurti savo patikrinimo metodus.
Yra keletas kitų būdų patikrinti duomenis prieš juos išsaugant į duomenų bazę, įskaitant natyvius duomenų bazės apribojimus, kliento pusės patikrinimus ir valdiklio lygio patikrinimus. Štai santrauka apie privalumus ir trūkumus:
- Duomenų bazės apribojimai ir/arba saugojami procedūros padaro patikrinimo mechanizmus priklausomus nuo duomenų bazės ir gali padaryti testavimą ir palaikymą sudėtingesnius. Tačiau, jei jūsų duomenų bazė naudojama kitų programų, gali būti gera idėja naudoti kai kuriuos apribojimus duomenų bazės lygmeniu. Be to, duomenų bazės lygio patikrinimai saugiai gali tvarkyti tam tikrus dalykus (pvz., unikalumą labai naudojamose lentelėse), kurie kitaip gali būti sunkiai įgyvendinami.
- Kliento pusės patikrinimai gali būti naudingi, bet paprastai yra nepatikimi, jei naudojami vieni. Jei jie įgyvendinami naudojant „JavaScript“, jie gali būti apeiti, jei naršyklėje naudotojas išjungia „JavaScript“. Tačiau, jei kombinuojami su kitomis technikomis, kliento pusės patikrinimas gali būti patogus būdas suteikti vartotojams nedelsiantinį atgalinį ryšį naudojant jūsų svetainę.
- Valdiklio lygio patikrinimai gali būti patrauklūs, bet dažnai tampa sunkiai valdomi ir sunkiai testuojami bei palaikomi. Kiek įmanoma, gerai būtų laikyti savo valdiklius paprastais, nes tai padarys jūsų programą malonų ilgalaikiam naudojimui.
Pasirinkite šiuos atvejus. „Rails“ komandos nuomone, modelio lygio patikrinimai yra tinkamiausi daugumoje atvejų.
1.2 Kada vykdomas patikrinimas?
Yra du rūšių Aktyvaus įrašo objektai: tie, kurie atitinka eilutę jūsų duomenų bazėje, ir tie, kurie to nedaro. Kai sukuriate naują objektą, pavyzdžiui, naudodami new
metodą, tas objektas dar nepriklauso duomenų bazei. Kai tik iškviečiate save
šiam objektui, jis bus išsaugotas atitinkamoje duomenų bazės lentelėje. Aktyvusis įrašas naudoja new_record?
objekto metodo, kad nustatytų, ar objektas jau yra duomenų bazėje ar ne. Apžvelkime šį Aktyvaus įrašo klasės pavyzdį:
class Person < ApplicationRecord
end
Galime pamatyti, kaip tai veikia žiūrint į kelias bin/rails console
išvestis:
irb> p = Person.new(name: "John Doe")
=> #<Person id: nil, name: "John Doe", created_at: nil, updated_at: nil>
irb> p.new_record?
=> true
irb> p.save
=> true
irb> p.new_record?
=> false
Naujo įrašo sukūrimas ir išsaugojimas siunčia SQL INSERT
operaciją į duomenų bazę. Esamo įrašo atnaujinimas siunčia SQL UPDATE
operaciją. Patikrinimai paprastai vykdomi prieš šias komandas siunčiant į duomenų bazę. Jei patikrinimai nepavyksta, objektas bus pažymėtas kaip negaliojantis ir Aktyvusis įrašas nevykdys INSERT
ar UPDATE
operacijos. Tai leidžia išvengti negaliojančio objekto saugojimo duomenų bazėje. Galite pasirinkti, kad tam tikri patikrinimai būtų vykdomi, kai objektas yra kuriamas, išsaugomas ar atnaujinamas.
DĖMESIO: Yra daug būdų pakeisti objekto būseną duomenų bazėje. Kai kurie metodai sukelia patikrinimus, bet kiti ne. Tai reiškia, kad galite išsaugoti objektą duomenų bazėje negaliojančioje būsenoje, jei nesate atsargūs. Šie metodai sukelia validacijas ir objektą įrašo į duomenų bazę tik tada, jei objektas yra galiojantis:
create
create!
save
save!
update
update!
Bang versijos (pvz., save!
) iškelia išimtį, jei įrašas yra negaliojantis.
Ne-bang versijos to nedaro: save
ir update
grąžina false
, o
create
grąžina objektą.
1.3 Validacijų praleidimas
Šie metodai praleidžia validacijas ir objektą įrašo į duomenų bazę, nepriklausomai nuo jo galiojimo. Jie turėtų būti naudojami atsargiai.
decrement!
decrement_counter
increment!
increment_counter
insert
insert!
insert_all
insert_all!
toggle!
touch
touch_all
update_all
update_attribute
update_column
update_columns
update_counters
upsert
upsert_all
Reikia pažymėti, kad save
taip pat gali praleisti validacijas, jei perduodamas validate:
false
argumentas. Šią techniką reikia naudoti atsargiai.
save(validate: false)
1.4 valid?
ir invalid?
Prieš įrašant Active Record objektą, „Rails“ vykdo jūsų validacijas. Jei šios validacijos sukelia klaidų, „Rails“ neįrašo objekto.
Galite taip pat patys paleisti šias validacijas. valid?
paleidžia jūsų validacijas
ir grąžina true
, jei objekte nerasta klaidų, ir false
kitu atveju.
Kaip matėte aukščiau:
class Person < ApplicationRecord
validates :name, presence: true
end
irb> Person.create(name: "John Doe").valid?
=> true
irb> Person.create(name: nil).valid?
=> false
Po to, kai Active Record atliko validacijas, bet kokie nesėkmės gali būti pasiektos
per errors
egzemplioriaus metodą, kuris grąžina klaidų kolekciją.
Pagal apibrėžimą, objektas yra galiojantis, jei ši kolekcija yra tuščia po paleidimo
validacijos.
Reikia pažymėti, kad sukurta objektas su new
nepraneša klaidų
net jei jis techniškai yra negaliojantis, nes validacijos automatiškai vykdomos
tik tada, kai objektas yra išsaugotas, pvz., naudojant create
arba save
metodus.
class Person < ApplicationRecord
validates :name, presence: true
end
irb> p = Person.new
=> #<Person id: nil, name: nil>
irb> p.errors.size
=> 0
irb> p.valid?
=> false
irb> p.errors.objects.first.full_message
=> "Name can’t be blank"
irb> p = Person.create
=> #<Person id: nil, name: nil>
irb> p.errors.objects.first.full_message
=> "Name can’t be blank"
irb> p.save
=> false
irb> p.save!
ActiveRecord::RecordInvalid: Validation failed: Name can’t be blank
irb> Person.create!
ActiveRecord::RecordInvalid: Validation failed: Name can’t be blank
invalid?
yra valid?
priešingybė. Jis paleidžia jūsų validacijas,
grąžindamas true
, jei objekte buvo rasta klaidų, ir false
kitu atveju.
1.5 errors[]
Norėdami patikrinti, ar tam tikras objekto atributas yra galiojantis arba ne, galite
naudoti errors[:attribute]
. Tai grąžina visų
:attribute
klaidų pranešimų masyvą. Jei nėra klaidų nurodytame
atribute, grąžinamas tuščias masyvas.
Šis metodas yra naudingas tik po paleidimo validacijų, nes jis tik
tikrina klaidų kolekciją ir pats nevykdo validacijų. Jis
skiriasi nuo ActiveRecord::Base#invalid?
metodo, kuris paaiškina aukščiau, nes
jis neįvertina objekto galiojimo kaip visumos. Jis tik patikrina
ar yra klaidų, rastų objekto atskirame atribute.
class Person < ApplicationRecord
validates :name, presence: true
end
irb> Person.new.errors[:name].any?
=> false
irb> Person.create.errors[:name].any?
=> true
Mes išsamiau aptarsime validacijos klaidas Dirbant su validacijos klaidomis skyriuje.
2 Validacijos pagalbininkai
Active Record siūlo daug iš anksto apibrėžtų validacijos pagalbininkų, kuriuos galite naudoti
tiesiogiai savo klasės apibrėžimuose. Šie pagalbininkai teikia bendras validacijos
taisykles. Kiekvieną kartą, kai validacija nesėkminga, klaida pridedama prie objekto errors
kolekcijos, ir tai susiję su tikrinamu atributu.
Kiekvienas pagalbininkas priima bet kokį atributo pavadinimų skaičių, todėl vienoje kodo eilutėje galite pridėti tą pačią rūšies validaciją keliems atributams.
Visi jie priima :on
ir :message
parinktis, kurios nurodo, kada
validacija turėtų būti vykdoma ir kokį pranešimą reikėtų pridėti prie errors
kolekcijos, jei ji nesėkminga, atitinkamai. :on
parinktis priima vieną iš reikšmių
:create
arba :update
. Kiekvienam validacijos pagalbininkui yra numatytas klaidos pranešimas.
Šie pranešimai naudojami, kai :message
parinktis nėra nurodyta. Pažiūrėkime į kiekvieną iš prieinamų pagalbininkų.
INFORMACIJA: Norėdami pamatyti sąrašą prieinamų numatytųjų pagalbininkų, pažiūrėkite
ActiveModel::Validations::HelperMethods
.
2.1 patvirtinimas
Šis metodas patikrina, ar žymimasis langelis naudotojo sąsajoje buvo pažymėtas, kai forma buvo pateikta. Tai dažniausiai naudojama, kai naudotojui reikia sutikti su jūsų programos paslaugų sąlygomis, patvirtinti, kad buvo perskaitytas tam tikras tekstas arba bet kokia panaši sąvoka.
class Person < ApplicationRecord
validates :terms_of_service, acceptance: true
end
Ši patikra atliekama tik tada, jei terms_of_service
nėra nil
.
Numatytasis klaidos pranešimas šiam pagalbininkui yra "turi būti priimtas".
Taip pat galite perduoti pasirinktinį pranešimą per message
parinktį.
class Person < ApplicationRecord
validates :terms_of_service, acceptance: { message: 'turi būti laikomasi' }
end
Taip pat gali būti naudojama :accept
parinktis, kuri nustato leistinas reikšmes, kurios bus laikomos priimtinomis. Numatytasis variantas yra ['1', true]
ir gali būti lengvai pakeistas.
class Person < ApplicationRecord
validates :terms_of_service, acceptance: { accept: 'taip' }
validates :eula, acceptance: { accept: ['TEISINGA', 'priimta'] }
end
Ši validacija yra labai specifinė interneto programoms ir šis 'acceptance' nereikia įrašyti jokioje duomenų bazėje. Jei neturite lauko tam, pagalbininkas sukurs virtualų atributą. Jei laukas egzistuoja jūsų duomenų bazėje, accept
parinktis turi būti nustatyta arba įtraukti true
, kitaip validacija nebus vykdoma.
2.2 patvirtinimas
Šį pagalbininką turėtumėte naudoti, kai turite du teksto laukus, kurie turėtų gauti tiksliai tą patį turinį. Pavyzdžiui, galite patvirtinti el. pašto adresą ar slaptažodį. Ši validacija sukuria virtualų atributą, kurio pavadinimas yra lauko, kurį reikia patvirtinti, pavadinimas su pridėtu "_confirmation".
class Person < ApplicationRecord
validates :email, confirmation: true
end
Šablone galite naudoti kažką panašaus į
<%= text_field :person, :email %>
<%= text_field :person, :email_confirmation %>
PASTABA: Ši patikra atliekama tik tada, jei email_confirmation
nėra nil
. Norėdami reikalauti patvirtinimo, įsitikinkite, kad pridėjote privalomą tikrinimą patvirtinimo atributui (apie tai daugiau žr. vėliau šiame vadove):
class Person < ApplicationRecord
validates :email, confirmation: true
validates :email_confirmation, presence: true
end
Taip pat yra :case_sensitive
parinktis, kurią galite naudoti, norėdami nustatyti, ar patvirtinimo apribojimas bus didžiosios ir mažosios raidės jautrus ar ne. Ši parinktis pagal nutylėjimą yra true
.
class Person < ApplicationRecord
validates :email, confirmation: { case_sensitive: false }
end
Numatytasis klaidos pranešimas šiam pagalbininkui yra "nesutampa su patvirtinimu". Taip pat galite perduoti pasirinktinį pranešimą per message
parinktį.
Daugiausia naudojant šį tikrinimą, norėsite jį sujungti su :if
parinktimi, kad patvirtinimo laukas "_confirmation" būtų tikrinamas tik tada, kai pradinis laukas pasikeitė ir ne kiekvieną kartą, kai įrašas išsaugomas. Daugiau apie sąlyginį tikrinimą vėliau.
class Person < ApplicationRecord
validates :email, confirmation: true
validates :email_confirmation, presence: true, if: :email_changed?
end
2.3 palyginimas
Ši patikra patikrins palyginimą tarp dviejų palyginamų reikšmių.
class Promotion < ApplicationRecord
validates :end_date, comparison: { greater_than: :start_date }
end
Numatytasis klaidos pranešimas šiam pagalbininkui yra "nepavyko palyginimas". Taip pat galite perduoti pasirinktinį pranešimą per message
parinktį.
Visos šios parinktys yra palaikomos:
:greater_than
- Nurodo, kad reikšmė turi būti didesnė nei nurodyta reikšmė. Numatytasis klaidos pranešimas šiai parinkčiai yra "turi būti didesnis nei %{count}".:greater_than_or_equal_to
- Nurodo, kad reikšmė turi būti didesnė arba lygi nurodytai reikšmei. Numatytasis klaidos pranešimas šiai parinkčiai yra "turi būti didesnis arba lygus %{count}".:equal_to
- Nurodo, kad reikšmė turi būti lygi nurodytai reikšmei. Numatytasis klaidos pranešimas šiai parinkčiai yra "turi būti lygus %{count}".:less_than
- Nurodo, kad reikšmė turi būti mažesnė nei nurodyta reikšmė. Numatytasis klaidos pranešimas šiai parinkčiai yra "turi būti mažesnis nei %{count}".:less_than_or_equal_to
- Nurodo, kad reikšmė turi būti mažesnė arba lygi nurodytai reikšmei. Numatytasis klaidos pranešimas šiai parinkčiai yra "turi būti mažesnis arba lygus %{count}".:other_than
- Nurodo, kad reikšmė turi būti skirtinga nuo nurodytos reikšmės. Numatytasis klaidos pranešimas šiai parinkčiai yra "turi būti skirtingas nei %{count}".
PASTABA: Validavimui reikalinga palyginimo parinktis. Kiekviena parinktis priima reikšmę, procedūrą arba simbolį. Bet kuri klasė, kuri įtraukia Comparable, gali būti palyginama.
2.4 formatas
Šis pagalbinis įrankis patikrina atributų reikšmes, tikrinant, ar jos atitinka nurodytą reguliariąją išraišką, kuri yra nurodoma naudojant :with
parinktį.
class Product < ApplicationRecord
validates :legacy_code, format: { with: /\A[a-zA-Z]+\z/,
message: "leidžia tik raides" }
end
Atvirkščiai, naudojant :without
parinktį, galite reikalauti, kad nurodytas atributas nesutaptų su reguliariąja išraiška.
Abiem atvejais, pateikta :with
arba :without
parinktis turi būti reguliariąja išraiška arba proc arba lambda funkcija, kurią grąžina.
Numatytoji klaidos žinutė yra "yra neteisinga".
ĮSPĖJIMAS. naudokite \A
ir \z
norėdami sutapti su eilutės pradžia ir pabaiga, ^
ir $
sutampa su eilutės pradžia / pabaiga. Dėl dažno ^
ir $
neteisingo naudojimo, jei naudojate bet kurį iš šių dviejų pririšiklių teikiamos reguliariosios išraiškos, turite perduoti multiline: true
parinktį. Daugeliu atvejų turėtumėte naudoti \A
ir \z
.
2.5 įtraukimas
Šis pagalbinis įrankis patikrina, ar atributų reikšmės yra įtrauktos į nurodytą rinkinį. Iš tikrųjų, šis rinkinys gali būti bet koks numeruojamas objektas.
class Coffee < ApplicationRecord
validates :size, inclusion: { in: %w(small medium large),
message: "%{value} nėra leistinas dydis" }
end
inclusion
pagalbinis įrankis turi :in
parinktį, kuri priima priimtinų reikšmių rinkinį. :in
parinktis turi sinonimą, vadinamą :within
, kurį galite naudoti tuo pačiu tikslu, jei norite. Ankstesnis pavyzdys naudoja :message
parinktį, kad parodytų, kaip galite įtraukti atributo reikšmę. Pilniems parinkčių nustatymams žr. žinučių dokumentaciją.
Numatytoji klaidos žinutė šiam pagalbiniam įrankiui yra "nėra sąraše".
2.6 neįtraukimas
Įtraukimo
priešingybė yra... neįtraukimas
!
Šis pagalbinis įrankis patikrina, ar atributų reikšmės nėra įtrauktos į nurodytą rinkinį. Iš tikrųjų, šis rinkinys gali būti bet koks numeruojamas objektas.
class Account < ApplicationRecord
validates :subdomain, exclusion: { in: %w(www us ca jp),
message: "%{value} yra rezervuotas." }
end
neįtraukimo
pagalbinis įrankis turi :in
parinktį, kuri priima reikšmių rinkinį, kuris nebus priimtas patikrinamiems atributams. :in
parinktis turi sinonimą, vadinamą :within
, kurį galite naudoti tuo pačiu tikslu, jei norite. Šis pavyzdys naudoja :message
parinktį, kad parodytų, kaip galite įtraukti atributo reikšmę. Pilniems žinutės argumento parinktims žr. žinučių dokumentaciją.
Numatytoji klaidos žinutė yra "yra rezervuotas".
Alternatyviai tradiciniam numeruojamam objektui (pvz., masyvui) galite pateikti proc, lambda arba simbolį, kuris grąžina numeruojamą objektą. Jei numeruojamas objektas yra skaitinis, laiko arba datos laiko intervalas, testas atliekamas naudojant Range#cover?
, kitu atveju naudojant include?
. Naudojant proc arba lambda, validuojamas egzempliorius, kuris yra perduodamas kaip argumentas.
2.7 ilgis
Šis pagalbinis įrankis patikrina atributų reikšmių ilgį. Jis suteikia įvairių parinkčių, todėl galite nurodyti ilgio apribojimus skirtingais būdais:
class Person < ApplicationRecord
validates :name, length: { minimum: 2 }
validates :bio, length: { maximum: 500 }
validates :password, length: { in: 6..20 }
validates :registration_number, length: { is: 6 }
end
Galimos ilgio apribojimo parinktys yra:
:minimum
- Atributas negali būti mažesnis nei nurodytas ilgis.:maximum
- Atributas negali būti didesnis nei nurodytas ilgis.:in
(arba:within
) - Atributo ilgis turi būti įtrauktas į nurodytą intervalą. Šios parinkties reikšmė turi būti intervalas.:is
- Atributo ilgis turi būti lygus nurodytai reikšmei.
Numatytosios klaidos žinutės priklauso nuo atliekamo ilgio patikrinimo tipo. Galite tinkinti šias žinutes, naudodami :wrong_length
, :too_long
ir :too_short
parinktis ir %{count}
kaip vietos rezervuotąjį ženklą, atitinkantį naudojamą ilgio apribojimą. Vis tiek galite naudoti :message
parinktį, norėdami nurodyti klaidos žinutę.
class Person < ApplicationRecord
validates :bio, length: { maximum: 1000,
too_long: "leidžiama daugiausiai %{count} simboliai" }
end
Atkreipkite dėmesį, kad numatytosios klaidos žinutės yra daugiskaitos (pvz., "yra per trumpas (minimumas yra %{count} simboliai)"). Dėl šios priežasties, kai :minimum
yra 1, turėtumėte nurodyti tinkintą žinutę arba vietoj to naudoti presence: true
. Kai :in
ar :within
turi apatinį ribą 1, turėtumėte arba nurodyti tinkintą žinutę, arba prieš length
iškviesti presence
.
PASTABA: Galima naudoti tik vieną apribojimo parinktį išskyrus :minimum
ir :maximum
parinktis, kurios gali būti derinamos kartu.
2.8 numericality
Šis pagalbininkas patikrina, ar jūsų atributai turi tik skaitines reikšmes. Pagal nutylėjimą jis atitiks pasirinktinį ženklą, po kurio seka sveikasis arba slankiojo kablelio skaičius.
Norėdami nurodyti, kad leidžiamos tik sveikosios skaičių reikšmės, nustatykite :only_integer
reikšmę į true
. Tada jis naudos šią reguliariąją išraišką, kad patikrintų atributo reikšmę.
/\A[+-]?\d+\z/
Kitu atveju jis bandys konvertuoti reikšmę į skaičių naudodamas Float
. Float
tipo reikšmės yra konvertuojamos į BigDecimal
naudojant stulpelio tikslumo reikšmę arba maksimaliai 15 skaitmenų.
class Player < ApplicationRecord
validates :points, numericality: true
validates :games_played, numericality: { only_integer: true }
end
Pagal nutylėjimą klaidos pranešimas dėl :only_integer
yra "turi būti sveikasis skaičius".
Be :only_integer
, šis pagalbininkas taip pat priima :only_numeric
parinktį, kuri nurodo, kad reikšmė turi būti Numeric
tipo objektas ir bandys ją analizuoti, jei ji yra String
tipo.
PASTABA: Pagal nutylėjimą numericality
neleidžia nil
reikšmių. Galite naudoti allow_nil: true
parinktį, kad tai leistų. Atkreipkite dėmesį, kad Integer
ir Float
tipo stulpeliuose tuščios eilutės konvertuojamos į nil
reikšmę.
Klaidos pranešimas pagal nutylėjimą, kai nėra nurodytų parinkčių, yra "nėra skaičius".
Taip pat yra daug parinkčių, kurios gali būti naudojamos pridėti apribojimus priimtinoms reikšmėms:
:greater_than
- Nurodo, kad reikšmė turi būti didesnė nei nurodyta reikšmė. Klaidos pranešimas pagal nutylėjimą šiai parinkčiai yra "turi būti didesnis nei %{count}".:greater_than_or_equal_to
- Nurodo, kad reikšmė turi būti didesnė arba lygi nurodytai reikšmei. Klaidos pranešimas pagal nutylėjimą šiai parinkčiai yra "turi būti didesnis arba lygus %{count}".:equal_to
- Nurodo, kad reikšmė turi būti lygi nurodytai reikšmei. Klaidos pranešimas pagal nutylėjimą šiai parinkčiai yra "turi būti lygus %{count}".:less_than
- Nurodo, kad reikšmė turi būti mažesnė nei nurodyta reikšmė. Klaidos pranešimas pagal nutylėjimą šiai parinkčiai yra "turi būti mažesnis nei %{count}".:less_than_or_equal_to
- Nurodo, kad reikšmė turi būti mažesnė arba lygi nurodytai reikšmei. Klaidos pranešimas pagal nutylėjimą šiai parinkčiai yra "turi būti mažesnis arba lygus %{count}".:other_than
- Nurodo, kad reikšmė turi būti skirtinga nuo nurodytos reikšmės. Klaidos pranešimas pagal nutylėjimą šiai parinkčiai yra "turi būti skirtingas nei %{count}".:in
- Nurodo, kad reikšmė turi būti nurodytame diapazone. Klaidos pranešimas pagal nutylėjimą šiai parinkčiai yra "turi būti diapazone %{count}".:odd
- Nurodo, kad reikšmė turi būti nelyginis skaičius. Klaidos pranešimas pagal nutylėjimą šiai parinkčiai yra "turi būti nelyginis".:even
- Nurodo, kad reikšmė turi būti lyginis skaičius. Klaidos pranešimas pagal nutylėjimą šiai parinkčiai yra "turi būti lyginis".
2.9 presence
Šis pagalbininkas patikrina, ar nurodyti atributai nėra tušti. Jis naudoja Object#blank?
metodą, kad patikrintų, ar reikšmė yra nil
arba tuščia eilutė, tai yra, eilutė, kuri yra tuščia arba susideda tik iš tarpų.
class Person < ApplicationRecord
validates :name, :login, :email, presence: true
end
Jei norite užtikrinti, kad asociacija yra pateikiama, turėsite patikrinti, ar pats asocijuotas objektas yra pateikiamas, o ne naudojamas svetainės raktas, skirtas susieti asociaciją. Taip pat yra patikrinama, ar ne tik svetainės raktas yra tuščias, bet ir ar nurodytas objektas egzistuoja.
class Supplier < ApplicationRecord
has_one :account
validates :account, presence: true
end
Norėdami patikrinti privalomų susijusių įrašų, jums reikia nurodyti :inverse_of
parinktį asociacijai:
class Order < ApplicationRecord
has_many :line_items, inverse_of: :order
end
PASTABA: Jei norite užtikrinti, kad asociacija būtų ne tik pateikiama, bet ir galiojanti, taip pat turite naudoti validates_associated
. Daugiau informacijos
žemiau
Jei patikrinate has_one
arba has_many
ryšiu susieto objekto pateikimą, bus patikrinta, ar objektas nėra blank?
ir ar jis nėra marked_for_destruction?
.
Kadangi false.blank?
yra tiesa, jei norite patikrinti, ar yra pateikiama boolean tipo lauko reikšmė, turėtumėte naudoti vieną iš šių patikrinimų:
# Reikšmė _turi būti_ true arba false
validates :boolean_field_name, inclusion: [true, false]
# Reikšmė _negali būti_ nil, tai yra, true arba false
validates :boolean_field_name, exclusion: [nil]
Naudodami vieną iš šių patvirtinimų, užtikrinsite, kad reikšmė NEBUS nil
, kas daugeliu atvejų rezultuotų NULL
reikšme.
Numatytasis klaidos pranešimas yra "negali būti tuščias".
2.10 absence
Šis pagalbininkas patikrina, ar nurodyti atributai yra nebuvę. Jis naudoja Object#present?
metodą, kad patikrintų, ar reikšmė nėra nei nil
, nei tuščias eilutės simbolis, t. y. eilutė, kuri yra tuščia arba susideda tik iš tarpų.
class Person < ApplicationRecord
validates :name, :login, :email, absence: true
end
Jei norite būti tikri, kad asociacija yra nebuvusi, turite patikrinti, ar pati susijusi objektas yra nebuvęs, o ne naudojamas svetainės raktas, skirtas susieti asociaciją.
class LineItem < ApplicationRecord
belongs_to :order
validates :order, absence: true
end
Norėdami patikrinti asocijuotus įrašus, kurių nebuvimas yra būtinas, turite nurodyti :inverse_of
parinktį asociacijai:
class Order < ApplicationRecord
has_many :line_items, inverse_of: :order
end
PASTABA: Jei norite užtikrinti, kad asociacija būtų ir esanti, ir galiojanti, taip pat turite naudoti validates_associated
. Daugiau informacijos
žr. žemiau
Jei patikrinate objekto nebuvimą, susijusį per has_one
arba
has_many
ryšį, bus patikrinta, ar objektas nėra nei present?
, nei
marked_for_destruction?
.
Kadangi false.present?
yra false
, jei norite patikrinti, ar logikos laukas yra nebuvęs,
turėtumėte naudoti validates :field_name, exclusion: { in: [true, false] }
.
Numatytasis klaidos pranešimas yra "turi būti tuščias".
2.11 uniqueness
Šis pagalbininkas patikrina, ar atributo reikšmė yra unikali tiesiog prieš objektas bus išsaugotas.
class Account < ApplicationRecord
validates :email, uniqueness: true
end
Patikrinimas vyksta atliekant SQL užklausą į modelio lentelę, ieškant esamo įrašo su ta pačia reikšme tame atribute.
Yra :scope
parinktis, kurią galite naudoti, norėdami nurodyti vieną ar daugiau atributų,
kurie naudojami riboti unikalumo patikrinimą:
class Holiday < ApplicationRecord
validates :name, uniqueness: { scope: :year,
message: "turėtų įvykti kartą per metus" }
end
ĮSPĖJIMAS. Šis patikrinimas nekuria unikalumo apribojimo duomenų bazėje, todėl gali atsitikti, kad du skirtingi duomenų bazės ryšiai sukurs du įrašus su ta pačia reikšme stulpelyje, kurį norite, kad būtų unikalus. Norėdami išvengti to, turite sukurti unikalų indeksą tame stulpelyje savo duomenų bazėje.
Norėdami pridėti unikalumo duomenų bazės apribojimą savo duomenų bazėje, naudokite
add_index
teiginį migracijoje ir įtraukite unique: true
parinktį.
Jei norite sukurti duomenų bazės apribojimą, kad būtų išvengta galimų pažeidimų
unikalumo patikrinimo, naudojant :scope
parinktį, turite sukurti unikalų
indeksą abiejuose stulpeliuose savo duomenų bazėje. Daugiau informacijos
žr. [MySQL vadovą][] dėl kelių stulpelių indeksų arba [PostgreSQL vadovą][] dėl pavyzdžių
unikalumo apribojimų, kurie nurodo grupę stulpelių.
Taip pat yra :case_sensitive
parinktis, kurią galite naudoti, nurodydami, ar
unikalumo apribojimas bus jautrus raidėms, nejautrus raidėms arba atitiks
numatytąją duomenų bazės susiejimą. Ši parinktis pagal numatymą atitinka numatytąją duomenų bazės
susiejimą.
class Person < ApplicationRecord
validates :name, uniqueness: { case_sensitive: false }
end
ĮSPĖJIMAS. Atkreipkite dėmesį, kad kai kurios duomenų bazės yra konfigūruotos atlikti neišskiriamus paieškas.
Yra :conditions
parinktis, kuria galite nurodyti papildomas sąlygas
WHERE
SQL fragmentui, kad apribotumėte unikalumo apribojimo paiešką (pvz.
sąlygos: -> { where(status: 'active') }
).
Numatytasis klaidos pranešimas yra "jau buvo užimta".
Daugiau informacijos žr. validates_uniqueness_of
.
2.12 validates_associated
Turėtumėte naudoti šį pagalbininką, kai jūsų modelyje yra asociacijos, kurios visada turi
būti patikrintos. Kiekvieną kartą, kai bandysite išsaugoti savo objektą, bus iškviesta
valid?
kiekvienam iš susijusių objektų.
class Library < ApplicationRecord
has_many :books
validates_associated :books
end
Šis patikrinimas veiks su visais asociacijos tipais.
ATSAKOMYBĖ: Nenaudokite validates_associated
abiejose asociacijų galuose.
Jos viena kitą iškvies begalinį ciklą.
Numatytasis klaidos pranešimas validates_associated
yra "yra neteisingas". Atkreipkite dėmesį,
kad kiekvienas susijęs objektas turės savo errors
kolekciją; klaidos
neperduodamos į iškviečiantį modelį.
PASTABA: validates_associated
gali būti naudojamas tik su ActiveRecord objektais,
viskas iki šiol taip pat gali būti naudojama su bet kuriuo objektu, kuriame yra
ActiveModel::Validations
.
2.13 validates_each
Šis pagalbininkas patikrina atributus prieš bloką. Jis neturi iš anksto nustatyto patikrinimo funkcijos. Turėtumėte sukurti vieną naudodami bloką, ir kiekvienas validates_each
perduotas atributas bus patikrintas prieš jį.
Pavyzdyje, kurį matote žemiau, mes atmetame vardus ir pavardes, kurios prasideda mažąja raidė.
class Person < ApplicationRecord
validates_each :name, :surname do |record, attr, value|
record.errors.add(attr, 'turi prasidėti didžiąja raidė') if /\A[[:lower:]]/.match?(value)
end
end
Bloke gaunamas įrašas, atributo pavadinimas ir atributo reikšmė.
Bloke galite daryti bet ką, norėdami patikrinti, ar duomenys yra teisingi. Jei patikrinimas nepavyksta, turėtumėte pridėti klaidą prie modelio, todėl jis tampa neteisingas.
2.14 validates_with
Šis pagalbininkas perduoda įrašą atskiram klasės patikrinimui.
class GoodnessValidator < ActiveModel::Validator
def validate(record)
if record.first_name == "Evil"
record.errors.add :base, "Ši asmenybė yra pikta"
end
end
end
class Person < ApplicationRecord
validates_with GoodnessValidator
end
validates_with
neturi numatytojo klaidos pranešimo. Klaidas įrašui reikia pridėti rankiniu būdu į klaidų kolekciją, esančią patikrinimo klasėje.
PASTABA: Klaidos, pridėtos prie record.errors[:base]
, susijusios su viso įrašo būsena.
Norėdami įgyvendinti validate
metodą, metodo apibrėžime turite priimti record
parametrą, kuris yra tikrinamas įrašas.
Jei norite pridėti klaidą konkrečiam atributui, perduokite jį kaip pirmąjį argumentą, pvz., record.errors.add(:first_name, "prašome pasirinkti kitą vardą")
. Mes išsamiau aptarsime [validavimo klaidas][] vėliau.
def validate(record)
if record.some_field != "priimtina"
record.errors.add :some_field, "šis laukas yra nepriimtinas"
end
end
validates_with
pagalbininkas priima klasę arba klasės sąrašą, kurį naudoti patikrinimui.
class Person < ApplicationRecord
validates_with MyValidator, MyOtherValidator, on: :create
end
Kaip ir visi kiti patikrinimai, validates_with
priima :if
, :unless
ir :on
parinktis. Jei perduodate kitas parinktis, jas bus perduodamos patikrinimo klasei kaip options
:
class GoodnessValidator < ActiveModel::Validator
def validate(record)
if options[:fields].any? { |field| record.send(field) == "Evil" }
record.errors.add :base, "Ši asmenybė yra pikta"
end
end
end
class Person < ApplicationRecord
validates_with GoodnessValidator, fields: [:first_name, :last_name]
end
Atkreipkite dėmesį, kad patikrintuvas bus inicializuotas tik vieną kartą visam programos gyvavimo ciklui, o ne kiekvienam patikrinimo paleidimui, todėl atsargiai naudokitės joje esančiomis objekto kintamomis.
Jei jūsų patikrinimas yra pakankamai sudėtingas, kad norėtumėte naudoti objekto kintamąsias, galite lengvai naudoti paprastą senąjį Ruby objektą:
class Person < ApplicationRecord
validate do |person|
GoodnessValidator.new(person).validate
end
end
class GoodnessValidator
def initialize(person)
@person = person
end
def validate
if some_complex_condition_involving_ivars_and_private_methods?
@person.errors.add :base, "Ši asmenybė yra pikta"
end
end
# ...
end
Mes išsamiau aptarsime papildomus patikrinimus vėliau.
3 Bendri patikrinimo parinktys
Yra keletas bendrų parinkčių, kurias palaiko ką tik aptartos patikrinimo priemonės, dabar aptarsime kai kurias iš jų!
PASTABA: Ne visos šios parinktys palaikomos visais patikrinimo priemonėmis, prašome kreiptis į ActiveModel::Validations
API dokumentaciją.
Naudodami bet kurį iš ką tik minėtų patikrinimo metodus, yra ir bendrų parinkčių sąrašas, bendrai naudojamas su patikrinimo priemonėmis. Dabar aptarsime šias parinktis!
:allow_nil
: Praleisti patikrinimą, jei atributas yranil
.:allow_blank
: Praleisti patikrinimą, jei atributas yra tuščias.:message
: Nurodyti pasirinktinį klaidos pranešimą.:on
: Nurodyti kontekstus, kuriuose šis patikrinimas yra aktyvus.:strict
: Iškelti išimtį, kai patikrinimas nepavyksta.:if
ir:unless
: Nurodyti, kada patikrinimas turėtų ar neturėtų įvykti.
3.1 :allow_nil
:allow_nil
parinktis praleidžia patikrinimą, kai tikrinama reikšmė yra nil
.
class Coffee < ApplicationRecord
validates :size, inclusion: { in: %w(small medium large),
message: "%{value} yra neteisingas dydis" }, allow_nil: true
end
irb> Coffee.create(size: nil).valid?
=> true
irb> Coffee.create(size: "mega").valid?
=> false
Dėl visų pasirinkimų, skirtų pranešimo argumentui, žr. pranešimo dokumentaciją.
3.2 :allow_blank
:allow_blank
parinktis panaši į :allow_nil
parinktį. Ši parinktis leidžia patikrinimui praeiti, jei atributo reikšmė yra blank?
, pvz., nil
arba tuščias eilutė.
class Topic < ApplicationRecord
validates :title, length: { is: 5 }, allow_blank: true
end
irb> Topic.create(title: "").valid?
=> true
irb> Topic.create(title: nil).valid?
=> true
3.3 :message
Kaip jau matėte, :message
parinktis leidžia nurodyti pranešimą, kuris bus pridėtas prie errors
kolekcijos, kai validacija nepavyks. Kai ši parinktis nenaudojama, Active Record naudos atitinkamą numatytąjį klaidos pranešimą kiekvienam validacijos pagalbininkui.
:message
parinktis priima String
arba Proc
kaip savo reikšmę.
String
:message
reikšmė gali būti pasirinktinai sudaryta iš %{value}
, %{attribute}
ir %{model}
, kurie bus dinamiškai pakeisti, kai validacija nepavyks. Šis pakeitimas atliekamas naudojant i18n gemą, ir vietos rezervavimo ženklai turi būti tiksliai atitinkantys, be jokių tarpų.
class Person < ApplicationRecord
# Kietas pranešimas
validates :name, presence: { message: "turi būti pateiktas, prašome" }
# Pranešimas su dinamine atributo reikšme. %{value} bus pakeistas
# tikra atributo reikšme. %{attribute} ir %{model} taip pat yra prieinami.
validates :age, numericality: { message: "%{value} atrodo neteisinga" }
end
Proc
:message
reikšmė gauna dvi argumentus: tikrinamas objektas ir :model
, :attribute
ir :value
raktų-reikšmių porų maišą.
class Person < ApplicationRecord
validates :username,
uniqueness: {
# objektas = tikrinamas žmogaus objektas
# duomenys = { model: "Person", attribute: "Username", value: <username> }
message: ->(objektas, duomenys) do
"Ei #{objektas.name}, #{duomenys[:value]} jau užimtas."
end
}
end
3.4 :on
:on
parinktis leidžia nurodyti, kada vykdoma validacija. Visų įdiegtų validacijos pagalbininkų numatytasis elgesys yra vykdyti ją išsaugojant (tie patys, kuriant naują įrašą, ir atnaujinant jį). Jei norite tai pakeisti, galite naudoti on: :create
, kad validacija būtų vykdoma tik kuriant naują įrašą, arba on: :update
, kad validacija būtų vykdoma tik atnaujinant įrašą.
class Person < ApplicationRecord
# bus galima atnaujinti el. paštą su pasikartojančia reikšme
validates :email, uniqueness: true, on: :create
# bus galima sukurti įrašą su ne skaitine amžiaus reikšme
validates :age, numericality: true, on: :update
# numatytasis (validuoja tiek kuriant, tiek atnaujinant)
validates :name, presence: true
end
Taip pat galite naudoti on:
, kad apibrėžtumėte pasirinktines kontekstus. Pasirinktiniai kontekstai turi būti iššaukiami iš anksto, perduodant konteksto pavadinimą valid?
, invalid?
arba save
.
class Person < ApplicationRecord
validates :email, uniqueness: true, on: :account_setup
validates :age, numericality: true, on: :account_setup
end
irb> person = Person.new(age: 'trisdešimt trys')
irb> person.valid?
=> true
irb> person.valid?(:account_setup)
=> false
irb> person.errors.messages
=> {:email=>["jau yra užimtas"], :age=>["nėra skaičius"]}
person.valid?(:account_setup)
vykdo abu tikrinimus, neišsaugodamas modelio. person.save(context: :account_setup)
išsaugo person
account_setup
kontekste prieš išsaugojimą.
Taip pat priimtinas simbolių masyvo perdavimas.
class Book
include ActiveModel::Validations
validates :title, presence: true, on: [:update, :ensure_title]
end
irb> book = Book.new(title: nil)
irb> book.valid?
=> true
irb> book.valid?(:ensure_title)
=> false
irb> book.errors.messages
=> {:title=>["negali būti tuščias"]}
Kai iššaukiama iš anksto nustatyta kontekstu, validacijos vykdomos tam kontekstui ir bet kurioms validacijoms be konteksto.
class Person < ApplicationRecord
validates :email, uniqueness: true, on: :account_setup
validates :age, numericality: true, on: :account_setup
validates :name, presence: true
end
irb> person = Person.new
irb> person.valid?(:account_setup)
=> false
irb> person.errors.messages
=> {:email=>["jau yra užimtas"], :age=>["nėra skaičius"], :name=>["negali būti tuščias"]}
Daugiau on:
naudojimo atvejų aptarsime atgalinio iškvietimo vadove.
4 Griežtos validacijos
Taip pat galite nurodyti, kad validacija būtų griežta ir iškeltų ActiveModel::StrictValidationFailed
išimtį, kai objektas yra netinkamas.
class Person < ApplicationRecord
validates :name, presence: { strict: true }
end
irb> Person.new.valid?
ActiveModel::StrictValidationFailed: Vardas negali būti tuščias
Taip pat galima perduoti pasirinktinę išimtį :strict
parinkčiai.
class Person < ApplicationRecord
validates :token, presence: true, uniqueness: true, strict: TokenGenerationException
end
irb> Person.new.valid?
TokenGenerationException: Token negali būti tuščias
5 Sąlyginė validacija
Kartais bus prasminga patikrinti objektą tik tada, kai tenkinamas tam tikras sąlyga. Tai galite padaryti naudodami :if
ir :unless
parinktis, kurios gali priimti simbolį, Proc
arba masyvą. Galite naudoti :if
parinktį, kai norite nurodyti, kada validacija turėtų įvykti. Alternatyviai, jei norite nurodyti, kada validacija neturėtų įvykti, galite naudoti :unless
parinktį.
5.1 Simbolio naudojimas su :if
ir :unless
Galite susieti :if
ir :unless
parinktis su simboliu, kuris atitinka metodo pavadinimą, kuris bus iškviestas prieš vykstant patikrinimui. Tai yra dažniausiai naudojama parinktis.
class Order < ApplicationRecord
validates :card_number, presence: true, if: :paid_with_card?
def paid_with_card?
payment_type == "card"
end
end
5.2 :if
ir :unless
naudojimas su Proc
Galima susieti :if
ir :unless
su Proc
objektu, kuris bus iškviestas. Proc
objekto naudojimas suteikia galimybę rašyti sąlygą vienoje eilutėje, o ne atskirame metode. Ši parinktis geriausiai tinka vienos eilutės kodui.
class Account < ApplicationRecord
validates :password, confirmation: true,
unless: Proc.new { |a| a.password.blank? }
end
Kadangi lambda
yra Proc
tipo objektas, jį taip pat galima naudoti rašant sąlygą vienoje eilutėje, pasinaudojant sutrumpinta sintakse.
validates :password, confirmation: true, unless: -> { password.blank? }
5.3 Grupavimo sąlyginės patikros
Kartais naudinga, kad kelios patikros naudotų vieną sąlygą. Tai galima lengvai pasiekti naudojant with_options
.
class User < ApplicationRecord
with_options if: :is_admin? do |admin|
admin.validates :password, length: { minimum: 10 }
admin.validates :email, presence: true
end
end
Visos patikros, esančios with_options
bloke, automatiškai praeina sąlygą if: :is_admin?
5.4 Sąlyginių patikrų derinimas
Kita vertus, kai kelios sąlygos nusako, ar turėtų vykti patikra, galima naudoti Array
. Be to, galite taikyti tiek :if
, tiek :unless
toje pačioje patikroje.
class Computer < ApplicationRecord
validates :mouse, presence: true,
if: [Proc.new { |c| c.market.retail? }, :desktop?],
unless: Proc.new { |c| c.trackpad.present? }
end
Patikra vykdoma tik tada, kai visos :if
sąlygos ir jokia :unless
sąlyga neigiamai įvertinamos.
6 Atliekant individualias patikras
Kai įprastos patikros pagalbininkai neatitinka jūsų poreikių, galite rašyti savo patikrinimo metodus arba patikrinimo metodus, kaip pageidaujate.
6.1 Individualūs patikrinimo metodai
Individualūs patikrinimo metodai yra klasės, paveldinčios ActiveModel::Validator
, objektai. Šios klasės turi įgyvendinti validate
metodą, kuris priima įrašą kaip argumentą ir atlieka patikrinimą. Individualus patikrinimo metodas yra iškviečiamas naudojant validates_with
metodą.
class MyValidator < ActiveModel::Validator
def validate(record)
unless record.name.start_with? 'X'
record.errors.add :name, "Pateikite vardą, prasidedantį X, prašome!"
end
end
end
class Person < ApplicationRecord
validates_with MyValidator
end
Paprastiausias būdas pridėti individualius patikrinimo metodus, skirtus tikrinti atskirus atributus, yra naudojant patogų ActiveModel::EachValidator
. Šiuo atveju individuali patikrinimo klasė turi įgyvendinti validate_each
metodą, kuris priima tris argumentus: įrašą, atributą ir atributo reikšmę perduotame įraše.
class EmailValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless URI::MailTo::EMAIL_REGEXP.match?(value)
record.errors.add attribute, (options[:message] || "nėra el. pašto adresas")
end
end
end
class Person < ApplicationRecord
validates :email, presence: true, email: true
end
Kaip parodyta pavyzdyje, galite taip pat derinti standartines patikras su savo individualiais patikrinimo metodais.
6.2 Individualūs metodai
Taip pat galite kurti metodus, kurie patikrina jūsų modelių būseną ir prideda klaidas į errors
kolekciją, kai jie yra netinkami. Tada turite užregistruoti šiuos metodus, naudodami validate
klasės metodą, perduodant simbolius, nurodančius patikrinimo metodų pavadinimus.
Vienam klasės metodui galite perduoti daugiau nei vieną simbolį, ir atitinkamos patikros bus vykdomos ta tvarka, kuria jos buvo užregistruotos.
valid?
metodas patikrins, ar errors
kolekcija yra tuščia, todėl jūsų individualūs patikrinimo metodai turėtų pridėti klaidas, kai norite, kad patikrinimas nepavyktų:
class Invoice < ApplicationRecord
validate :expiration_date_cannot_be_in_the_past,
:discount_cannot_be_greater_than_total_value
def expiration_date_cannot_be_in_the_past
if expiration_date.present? && expiration_date < Date.today
errors.add(:expiration_date, "negali būti praeityje")
end
end
def discount_cannot_be_greater_than_total_value
if discount > total_value
errors.add(:discount, "negali būti didesnis nei bendra vertė")
end
end
end
Pagal numatytuosius nustatymus tokios patikros bus vykdomos kiekvieną kartą, kai iškviečiate valid?
arba išsaugojate objektą. Tačiau taip pat galima kontroliuoti, kada vykdyti šias individualias patikras, suteikiant :on
parinktį validate
metode, su :create
arba :update
.
class Invoice < ApplicationRecord
validate :active_customer, on: :create
def active_customer
errors.add(:customer_id, "nėra aktyvus") unless customer.active?
end
end
Daugiau informacijos apie :on
rasite aukščiau esančiame skyriuje.
6.3 Validatorių sąrašas
Jei norite sužinoti visus validacijos metodus tam tikram objektui, žvilgtelkite į validators
.
Pavyzdžiui, jei turime šį modelį, kuriame naudojamas pasirinktinis ir įdiegtas validatorius:
class Person < ApplicationRecord
validates :name, presence: true, on: :create
validates :email, format: URI::MailTo::EMAIL_REGEXP
validates_with MyOtherValidator, strict: true
end
Dabar galime naudoti validators
"Person" modelyje, kad pamatytume visus validacijos metodus arba netikrintume konkretaus lauko naudojant validators_on
.
irb> Person.validators
#=> [#<ActiveRecord::Validations::PresenceValidator:0x10b2f2158
@attributes=[:name], @options={:on=>:create}>,
#<MyOtherValidatorValidator:0x10b2f17d0
@attributes=[:name], @options={:strict=>true}>,
#<ActiveModel::Validations::FormatValidator:0x10b2f0f10
@attributes=[:email],
@options={:with=>URI::MailTo::EMAIL_REGEXP}>]
#<MyOtherValidator:0x10b2f0948 @options={:strict=>true}>]
irb> Person.validators_on(:name)
#=> [#<ActiveModel::Validations::PresenceValidator:0x10b2f2158
@attributes=[:name], @options={on: :create}>]
7 Darbas su validacijos klaidomis
Metodai valid?
ir invalid?
suteikia tik santraukos būseną apie validumą. Tačiau galite giliau įsikasti į kiekvieną atskirą klaidą, naudodami įvairius metodus iš kolekcijos errors
.
Štai dažniausiai naudojami metodai. Norėdami pamatyti visus galimus metodus, kreipkitės į dokumentaciją ActiveModel::Errors
.
7.1 errors
Tai yra vartai, per kuriuos galite giliau įsikasti į kiekvienos klaidos detales.
Tai grąžina klasės ActiveModel::Errors
pavyzdį, kuriame yra visos klaidos, kiekviena klaida yra vaizduojama ActiveModel::Error
objektu.
class Person < ApplicationRecord
validates :name, presence: true, length: { minimum: 3 }
end
irb> person = Person.new
irb> person.valid?
=> false
irb> person.errors.full_messages
=> ["Name can’t be blank", "Name is too short (minimum is 3 characters)"]
irb> person = Person.new(name: "John Doe")
irb> person.valid?
=> true
irb> person.errors.full_messages
=> []
irb> person = Person.new
irb> person.valid?
=> false
irb> person.errors.first.details
=> {:error=>:too_short, :count=>3}
7.2 errors[]
errors[]
naudojamas, kai norite patikrinti klaidų pranešimus apie konkretų atributą. Tai grąžina masyvą su visais klaidų pranešimais, susijusiais su nurodytu atributu, kiekvienas pranešimas yra vienas klaidos pranešimas. Jei atributui nėra klaidų, grąžinamas tuščias masyvas.
class Person < ApplicationRecord
validates :name, presence: true, length: { minimum: 3 }
end
irb> person = Person.new(name: "John Doe")
irb> person.valid?
=> true
irb> person.errors[:name]
=> []
irb> person = Person.new(name: "JD")
irb> person.valid?
=> false
irb> person.errors[:name]
=> ["is too short (minimum is 3 characters)"]
irb> person = Person.new
irb> person.valid?
=> false
irb> person.errors[:name]
=> ["can’t be blank", "is too short (minimum is 3 characters)"]
7.3 errors.where
ir klaidų objektas
Kartais mums gali prireikti daugiau informacijos apie kiekvieną klaidą, be jos pranešimo. Kiekviena klaida yra supakuota kaip ActiveModel::Error
objektas, o where
metodas yra dažniausias būdas pasiekti jį.
where
grąžina klaidų objektų masyvą, filtruotą pagal įvairias sąlygas.
class Person < ApplicationRecord
validates :name, presence: true, length: { minimum: 3 }
end
Galime filtruoti tik pagal atributą
, perduodant jį kaip pirmąjį parametrą į errors.where(:attr)
. Antrasis parametras naudojamas filtruoti norimą klaidos tipą
, iškviečiant errors.where(:attr, :type)
.
irb> person = Person.new
irb> person.valid?
=> false
irb> person.errors.where(:name)
=> [ ... ] # visos klaidos, susijusios su atributu :name
irb> person.errors.where(:name, :too_short)
=> [ ... ] # :too_short klaidos, susijusios su atributu :name
Galiausiai galime filtruoti pagal bet kokias parinktis
, kurios gali egzistuoti tam tikro tipo klaidos objekte.
irb> person = Person.new
irb> person.valid?
=> false
irb> person.errors.where(:name, :too_short, minimum: 3)
=> [ ... ] # visos vardo klaidos, būnant per trumpam ir minimumas yra 2
Iš šių klaidų objektų galite gauti įvairią informaciją:
irb> error = person.errors.where(:name).last
irb> error.attribute
=> :name
irb> error.type
=> :too_short
irb> error.options[:count]
=> 3
Taip pat galite generuoti klaidos pranešimą:
irb> error.message
=> "is too short (minimum is 3 characters)"
irb> error.full_message
=> "Name is too short (minimum is 3 characters)"
Metodas full_message
sugeneruoja draugiškesnį vartotojui pranešimą, su didžiąja raidės pradžioje esančiu atributo pavadinimu. (Norėdami tinkinti full_message
naudojamą formatą, žr. I18n vadovą.)
7.4 errors.add
Metodas add
sukuria klaidos objektą, paimdamas atributą
, klaidos tipą
ir papildomą parinkčių maišą. Tai naudinga, rašant savo validatorių, nes leidžia apibrėžti labai specifines klaidos situacijas.
class Person < ApplicationRecord
validate do |person|
errors.add :name, :too_plain, message: "is not cool enough"
end
end
irb> person = Person.create
irb> person.errors.where(:name).first.type
=> :too_plain
irb> person.errors.where(:name).first.full_message
=> "Vardas nepakankamai įdomus"
7.5 errors[:base]
Galite pridėti klaidas, kurios susijusios su objekto būsena kaip visuma, o ne
susijusios su konkrečiu atributu. Norėdami tai padaryti, turite naudoti :base
kaip
atributą pridedant naują klaidą.
class Person < ApplicationRecord
validate do |person|
errors.add :base, :invalid, message: "Šis žmogus yra netinkamas, nes ..."
end
end
irb> person = Person.create
irb> person.errors.where(:base).first.full_message
=> "Šis žmogus yra netinkamas, nes ..."
7.6 errors.size
size
metodas grąžina visų objekto klaidų skaičių.
class Person < ApplicationRecord
validates :name, presence: true, length: { minimum: 3 }
end
irb> person = Person.new
irb> person.valid?
=> false
irb> person.errors.size
=> 2
irb> person = Person.new(name: "Andrea", email: "[email protected]")
irb> person.valid?
=> true
irb> person.errors.size
=> 0
7.7 errors.clear
clear
metodas naudojamas, kai norite išvalyti errors
kolekciją. Žinoma, iškvietus errors.clear
netinkamam objektui, jis nebus
tapatybė: errors
kolekcija bus tuščia, bet kitą kartą, kai iškviestumėte valid?
ar bet kurį metodą, kuris bandytų išsaugoti šį objektą į
duomenų bazę, validacijos bus paleistos iš naujo. Jei viena iš validacijų nepavyks, errors
kolekcija bus užpildyta iš naujo.
class Person < ApplicationRecord
validates :name, presence: true, length: { minimum: 3 }
end
irb> person = Person.new
irb> person.valid?
=> false
irb> person.errors.empty?
=> false
irb> person.errors.clear
irb> person.errors.empty?
=> true
irb> person.save
=> false
irb> person.errors.empty?
=> false
8 Klaidų rodymas peržiūroje
Kai sukūrėte modelį ir pridėjote validacijas, jei šis modelis yra sukurtas per internetinę formą, tikriausiai norite rodyti klaidos pranešimą, kai viena iš validacijų nepavyksta.
Kadangi kiekviena programa tai tvarko skirtingai, „Rails“ neįtraukia jokių pagalbinių funkcijų, kurios padėtų jums tiesiogiai generuoti šiuos pranešimus. Tačiau, dėl gausybės metodų, kuriuos „Rails“ suteikia bendrai sąveikai su validacijomis, galite sukurti savo. Be to, generuojant skeletą, „Rails“ į _form.html.erb
įdeda tam tikrą ERB kodą, kuris rodo visą klaidų sąrašą šiame modelyje.
Tarkime, turime modelį, kuris yra išsaugotas kintamajame @article
, tai atrodo taip:
<% if @article.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@article.errors.count, "klaida") %> neleido išsaugoti šio straipsnio:</h2>
<ul>
<% @article.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
Be to, jei naudojate „Rails“ formos pagalbinius metodus, kai
validacijos klaida įvyksta lauke, jis sugeneruos papildomą <div>
aplink
įrašą.
<div class="field_with_errors">
<input id="article_title" name="article[title]" size="30" type="text" value="">
</div>
Tuomet galite pritaikyti šį div pagal savo poreikius. Numatytasis skeletas, kurį generuoja „Rails“, pavyzdžiui, prideda šį CSS taisyklę:
.field_with_errors {
padding: 2px;
background-color: red;
display: table;
}
Tai reiškia, kad bet koks laukas su klaida gali turėti 2 pikselių raudoną rėmelį.
Atsiliepimai
Jūs esate skatinami padėti pagerinti šio vadovo kokybę.
Prašome prisidėti, jei pastebite rašybos klaidų ar faktinių klaidų. Norėdami pradėti, galite perskaityti mūsų dokumentacijos prisidėjimo skyrių.
Taip pat gali būti nepilnos informacijos arba informacijos, kuri nėra atnaujinta. Prašome pridėti bet kokią trūkstamą dokumentaciją pagrindiniam. Patikrinkite Edge vadovus pirmiausia, ar problemas jau išspręsta arba ne pagrindinėje šakoje. Patikrinkite Ruby on Rails vadovų gaires dėl stiliaus ir konvencijų.
Jei dėl kokios nors priežasties pastebite kažką, ką reikia ištaisyti, bet negalite patys tai pataisyti, prašome pranešti apie problemą.
Ir galiausiai, bet ne mažiau svarbu, bet koks diskusijos dėl Ruby on Rails dokumentacijos yra labai laukiamos oficialiame Ruby on Rails forume.