7 Validation - Reference Documentation
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith
Version: null
Table of Contents
7 Validation
Grails validation capability is built on Spring's Validator API and data binding capabilities. However Grails takes this further and provides a unified way to define validation "constraints" with its constraints mechanism.
Grails validation ถูกสร้างขึ้นโดยใช้พื้นฐานของ Spring's Validator API และความสามารถใน data binding แต่ทั้งนี้ทั้งนั้น Grails สามารถต่อยอดได้โดยการกำหนด "constraints"
Constraints in Grails are a way to declaratively specify validation rules. Most commonly they are applied to domain classes, however URL Mappings and Command Objects also support constraints.
Constraints ใน Grails เป็นวิธีการกำหนดกฏของ validation โดยส่วนใหญ่แล้วเราจะใช้ domain classes แต่เราอาจจะใช้ URL Mappings และ Command Objects ก็ได้
7.1 Declaring Constraints
Within a domain class constraints are defined with the constraints property that is assigned a code block:
ในโดเมนคลาส constraints จะถูกกำหนดไว้ในค่าของ constraints ที่อยู่ในบล๊อกของโค๊ดclass User {
String login
String password
String email
Integer age static constraints = {
…
}
}
You then use method calls that match the property name for which the constraint applies in combination with named parameters to specify constraints:
โดยคุณก็จะสามารถเรียกใช้ method ที่ตรงกับชื่อของค่านั้นสำหรับแต่ล่ะ constraintclass User {
... static constraints = {
login size: 5..15, blank: false, unique: true
password size: 5..15, blank: false
email email: true, blank: false
age min: 18
}
}
In this example we've declared that the
ในตัวอย่างนี้เราประกาศค่า login property must be between 5 and 15 characters long, it cannot be blank and must be unique. We've also applied other constraints to the password, email and age properties.
login ว่าจะต้องมีตัวอักษรระหว่าง 5 ถึง 15 โดยไม่สามารถเป็นค่าว่างได้และต้องเป็นค่าเฉพาะตัว เราก็ยังกำหนดค่าของ password, email และ age ด้วยBy default, all domain class properties are not nullable (i.e. they have an implicitโดยปกติแล้วค่าของโดเมนคลาสทั้งหมดจะไม่สามารถเป็นค่าว่างได้ โดยจะถูกกำหนดไว้nullable: falseconstraint). The same is not true for command object properties, which are nullable by default.nullable: falseconstraint โดยหลักการนี้จะไม่ตรงกับ command object เพราะแต่ล่ะค่าจะเป็นค่าว่างโดยปกติ
A complete reference for the available constraints can be found in the Quick Reference section under the Constraints heading.
โดยข้อมูลอ้างอิงโดยสมบูรณ์จะสามารถหาได้จาก Quick Reference ในหัวข้อ ConstraintsA word of warning - referencing domain class properties from constraints
It's very easy to attempt to reference instance variables from the static constraints block, but this isn't legal in Groovy (or Java). If you do so, you will get a
เป็นการง่ายมากที่จะลองใช้ค่าตัวแปร instance ในบล๊อกของ static constraints แต่นี้ไม่ถูกต้องตามหลักของ Groovy หรือแม้แต่ Java ถ้าคุณทำแบบนั้นคุณก็จะถูกแจ้งว่า MissingPropertyException for your trouble. For example, you may try
MissingPropertyException โดยดังเช่นตัวอย่างclass Response {
Survey survey
Answer answer static constraints = {
survey blank: false
answer blank: false, inList: survey.answers
}
}
See how the
โดยคุณจะเห็นได้ว่า inList constraint references the instance property survey? That won't work. Instead, use a custom validator:
inList constraint อ้างอิงกับค่าของ survey ซึ่งแบบนี้จะไม่ถูกต้องโดยเราจะต้องใช้ custom validator แทนclass Response {
…
static constraints = {
survey blank: false
answer blank: false, validator: { val, obj -> val in obj.survey.answers }
}
}
In this example, the
ในตัวอย่างนี้ ค่า obj argument to the custom validator is the domain instance that is being validated, so we can access its survey property and return a boolean to indicate whether the new value for the answer property, val, is valid.
obj เป็นค่าที่ถูกกำหนดขึ้นมาเองโดยเป็น instance ที่ถูกตรวจสอบ โดยเราสามารถเข้าถึง survey โดยการคืนค่า boolean เพื่อแสดงให้เห็นว่าค่า answer, val นั้นถูกต้องหรือเปล่า
7.2 Validating Constraints
Validation Basics
Call the validate method to validate a domain class instance:
เรียกใช้ validate เพื่อการตรวจสอบความผิดพลาดของ โดเมนdef user = new User(params)if (user.validate()) { // do something with user } else { user.errors.allErrors.each { println it } }
The
ค่า errors property on domain classes is an instance of the Spring Errors interface. The Errors interface provides methods to navigate the validation errors and also retrieve the original values.
errors ในโดเมนเป้น instance ของอินเตอร์เฟส Errors ในสปริง Errors อินเตอร์เฟสจะสามารถเรียกใช้ method เพื่อการหาข้อผิดพลาดและการเรียกข้อมูลที่ผิดพลาดขึ้นมาได้ด้วยValidation Phases
Within Grails there are two phases of validation, the first one being data binding which occurs when you bind request parameters onto an instance such as:
ใน Grails จะมีสองระดับในการตรวจสอบความผิดพลาด ระดับที่หนึ่งคือ data binding ที่จะเกิดขึ้นเมื่อคุณเรียกข้อมูลจาก instance หนึ่งๆเช่นdef user = new User(params)
At this point you may already have errors in the
โดยในจุดนี้คุณสามารถมีข้อผิดพลาดได้จากการเปลี่ยนกลับของ type เช่น เปลี่ยนจาก Strings เป็น Dates คุณสามารถตรวจสอบได้โดยการใช้ errors property due to type conversion (such as converting Strings to Dates). You can check these and obtain the original input value using the Errors API:
Errorsif (user.hasErrors()) { if (user.errors.hasFieldErrors("login")) { println user.errors.getFieldError("login").rejectedValue } }
The second phase of validation happens when you call validate or save. This is when Grails will validate the bound values againts the constraints you defined. For example, by default the save method calls
ระดับที่สองจะเกิดขึ้นเมื่อคุณเรียกใช้ validate หรือ save ในขั้นตอนนี้ Grails จะทำการตรวจสอบค่ากับ constraints ที่คุณกำหนดไว้ เช่น โดยปกติแล้ว save จะเรียกใช้ validate before executing, allowing you to write code like:
validate ก่อนที่จะทำการใดๆโดยคุณก็จะสามารถเขียนโค๊ดได้ตามตัวอย่างด้านล่างif (user.save()) { return user } else { user.errors.allErrors.each { println it } }
7.3 Validation on the Client
Displaying Errors
Typically if you get a validation error you redirect back to the view for rendering. Once there you need some way of displaying errors. Grails supports a rich set of tags for dealing with errors. To render the errors as a list you can use renderErrors:
โดยปกติแล้วถ้าพบว่ามีข้อผิดพลาดเกิดขึ้น เราก็ต้องการที่จะกลับไปยังหน้าแสดงผล เพื่อแสดงข้อความข้อผิดพลาดนั้นๆ Grails สนับสนุนการแสดงนี้โดยใช้ tags เพื่อการแสดงข้อความที่ผิดพลาดโดยใช้ renderErrors<g:renderErrors bean="${user}" /><g:hasErrors bean="${user}"> <ul> <g:eachError var="err" bean="${user}"> <li>${err}</li> </g:eachError> </ul> </g:hasErrors>
Highlighting Errors
It is often useful to highlight using a red box or some indicator when a field has been incorrectly input. This can also be done with the hasErrors by invoking it as a method. For example:
โดยส่วนใหญ่แล้วเราจะแสดงข้อความโดยใช้กล่องข้อความสีแดง เมื่อฟิลด์นั้นๆถูกใส่ข้อมูลที่ผิดพลาด เราสามารถใช้วิธีนี้ได้โดยใช้ hasErrors<div class='value ${hasErrors(bean:user,field:'login','errors')}'> <input type="text" name="login" value="${fieldValue(bean:user,field:'login')}"/> </div>
This code checks if the
โค๊ดในส่วนนี้จะตรวจสอบว่า login field of the user bean has any errors and if so it adds an errors CSS class to the div, allowing you to use CSS rules to highlight the div.
login ฟิลด์ของ user นั่นมีข้อผิดพลาดตรงไหนหรือเปล่า ถ้ามีก็จะเพิ่มลงไปใน errors ลงในคลาส CSS ของ div เพื่อให้ div นั้นแสดงกล่องข้อความสีแดงออกมาจาก CSS ที่เพิ่มไปRetrieving Input Values
Each error is actually an instance of the FieldError class in Spring, which retains the original input value within it. This is useful as you can use the error object to restore the value input by the user using the fieldValue tag:
แต่ล่ะข้อความคือหนึ่ง instance ของ FieldError ในสปริงและก็จะมีค่าใสตัวของมันเอง โดยจะมีประโยชน์ในการใช้ error ออปเจกนั้นสำหรับเก็บค่าจากผู้ใช้โดยใช้ fieldValue tag<input type="text" name="login" value="${fieldValue(bean:user,field:'login')}"/>
This code will check for an existing
โค๊ดส่วนนี้จะตรวจสอบค่า FieldError in the User bean and if there is obtain the originally input value for the login field.
FieldError ที่มีอยู่แล้วใน User bean ถ้ามีก็จะเก็บค่านั้นลงใปในฟิลด์ login
7.4 Validation and Internationalization
Another important thing to note about errors in Grails is that error messages are not hard coded anywhere. The FieldError class in Spring resolves messages from message bundles using Grails' i18n support.
สิ่งสำคัญอีกอย่างนึงที่น่าจดจำไว้คือ ข้อความที่แสดงต่างๆใน Grails ไม่ได้ถูกกำหนดตายตัวไว้ในโค๊ดที่ไหน แต่คลาส FieldError ในสปริงเป็นตัวเรียกข้อความนั้นๆมาจาก message bundles โดยใช้ การสนับสนุนของ Grails' i18nConstraints and Message Codes
The codes themselves are dictated by a convention. For example consider the constraints we looked at earlier:
โดยโค๊ดนั้นถูกกำหนดไว้อยู่แล้ว เช่นจากตัวอย่างด้านล่างโดยมองจาก constraints แล้วpackage com.mycompany.myappclass User { ... static constraints = { login size: 5..15, blank: false, unique: true password size: 5..15, blank: false email email: true, blank: false age min: 18 } }
If a constraint is violated Grails will by convention look for a message code of the form:
ถ้า constraint ไม่เป็นไปตามกฏ Grails ก็จะเรียกข้อความมาจาก[Class Name].[Property Name].[Constraint Code]
In the case of the
โดยในตัวอย่างนี้ blank constraint this would be user.login.blank so you would need a message such as the following in your grails-app/i18n/messages.properties file:
blank constraint ก็จะเป็น user.login.blank โดยคุณก็จะต้องมีค่านี้ในไฟล์ grails-app/i18n/messages.properties ด้วยuser.login.blank=Your login name must be specified!
The class name is looked for both with and without a package, with the packaged version taking precedence. So for example, com.mycompany.myapp.User.login.blank will be used before user.login.blank. This allows for cases where your domain class message codes clash with a plugin's.
โดยชื่อของคลาสจะถูกค้นหาโดยมีแพกเกจหรือไม่มีแพกเกจก็ได้ แต่ ถ้ามีแพกเกจ Grails จะให้ความสำคัญมากกว่า เช่น com.mycompany.myapp.User.login.blank ก็จะถูกเรียกก่อน user.login.blank ทั้งนี้ทั้งนั้นเพื่อในกรณีที่ คลาสโดเมนมีชื่อตรงกับคลาสใดๆในปลั๊กอิน
For a reference on what codes are for which constraints refer to the reference guide for each constraint.
สำหรับการอ้างอิงว่าค่าใดใช้สำหรับ constraints ใดสามารถอ้างอิงได้จาก reference guide สำหรับแต่ล่ะ constraintDisplaying Messages
The renderErrors tag will automatically look up messages for you using the message tag. If you need more control of rendering you can handle this yourself:
renderErrors tag นี้ก็จะมองหา message tag ก่อนถ้าคุณต้องการความยืดหยุ่นมากกว่านั้นก็อาจจะกำหนดได้เองโดยตัวอย่างด้านล่าง<g:hasErrors bean="${user}"> <ul> <g:eachError var="err" bean="${user}"> <li><g:message error="${err}" /></li> </g:eachError> </ul> </g:hasErrors>
In this example within the body of the eachError tag we use the message tag in combination with its
ในตัวอย่างนี้ในบอดี้ของ eachError เราใช้ message tag และผสมผสานกับค่า error argument to read the message for the given error.
error เพื่ออ่านข้อความสำหรับแต่ล่ะข้อผิดพลาด
7.5 Validation Non Domain and Command Object Classes
Domain classes and command objects support validation by default. Other classes may be made validateable by defining the static
Domain classes และ command objects สนับสนุนการตรวจสอบข้อผิดพลาดโดยปกติอยู่แล้ว ถ้าสำหรับคลาสอื่นๆก็สามารถทำให้ตรวจสอบข้อผิดพลาดได้ โดยการกำหนดค่า static constraints property in the class (as described above) and then telling the framework about them. It is important that the application register the validateable classes with the framework. Simply defining the constraints property is not sufficient.
constraints ในคลาสนั้นๆ แล้วบอกกับ Grails ให้รับรู้ถึงคลาสนั้นๆ การบอกให้ Grails รับรู้ถึงการมีอยู่ของคลาสนั้นๆมีความสำคัญมาก โดยเพียงการกำหนด constraints นั้นไม่พอเพียง โดยจะเห็นได้จากตัวอย่างด้านล่างThe Validateable Annotation
Classes which define the static
คลาสที่กำหนดค่า static constraints property and are annotated with @Validateable can be made validateable by the framework. Consider this example:
constraints และประกาศ @Validateable ไว้ด้วยสามารถจะทำให้เป็นคลาสที่ตรวจสอบความผิดพลาดได้ โดยจะเห็นได้จากตัวอย่างด้านล่าง// src/groovy/com/mycompany/myapp/User.groovy package com.mycompany.myappimport org.codehaus.groovy.grails.validation.Validateable@Validateable class User { ... static constraints = { login size: 5..15, blank: false, unique: true password size: 5..15, blank: false email email: true, blank: false age min: 18 } }
You tell the framework which packages to search for
คุณต้องบอกกับ Grails ว่า แพกเกจในให้ทำการค้นหา Validateable classes in by assigning a list of Strings to the grails.validateable.packages property in Config.groovy:
Validateable โดยการกำหนดค่าสตริงใน grails.validateable.packages ใน Config.groovy:grails.validateable.packages = ['com.mycompany.dto', 'com.mycompany.util']
The framework will only search those packages (and child packages of those) for classes annotated with
เฟรมเวิกจะทำการค้นหาเฉพาะในแพกเกจนั้นๆและ แพกเกจลูกโดยหาจาก @Validateable.
@ValidateableRegistering Validateable Classes
If a class is not marked with
ถ้าคลาสนั้นไม่ได้ถูกกำหนดให้เป็น Validateable, it may still be made validateable by the framework. The steps required to do this are to define the static constraints property in the class (as described above) and then telling the framework about the class by assigning a value to the grails.validateable.classes property in Config.groovy@:
Validateable เราก็ยังสามารถทำให้เป็นคลาสที่ถูกตรวจสอบความผิดพลาดได้โดยเฟรมเวิก โดยนอกจากกำหนดค่า static constraints ในคลาสดั่งที่เห็นในตัวอย่างด้านบนแล้ว เราก็ยังต้องบอกกับเฟรมเวิกถึงการมีอยู่ของคลาสนั้นด้วยโดยการคำหนดค่า grails.validateable.classes ใน Config.groovy@:grails.validateable.classes = [com.mycompany.myapp.User, com.mycompany.dto.Account]

