2012-08-23 12 views
18

खेल में का उपयोग कर रूपों में क्षेत्र की वैधता सुनिश्चित करें! ढांचा, स्केला का उपयोग कर, कहते हैं कि मैं एक रूप है कि इस प्रकार जैसे:प्ले करें! ढांचा 2.0: अन्य क्षेत्रों

import play.api.data._ 
import play.api.data.Forms._ 
import play.api.data.validation.Constraints._ 

case class User(someStringField: String, someIntField: Int) 

val userForm = Form(
    mapping(
    "someStringField" -> text, 
    "someIntField" -> number verifying(x => SomeMethodThatReceivesAnIntAndReturnsABoolean(x)) 
)(User.apply)(User.unapply) 

)

जहां SomeMethodThatReceivesAnIntAndReturnsABoolean एक विधि है कि पूर्णांक पर कुछ तर्क यह मान्य करने के लिए करता है।

हालांकि, someIntField को सत्यापित करते समय मैं someStringField के मान पर विचार करने में सक्षम होना चाहता हूं, क्या यह खेल ढांचे के रूपों में इसे प्राप्त करने का एक तरीका है? मुझे पता है कि मैं कुछ ऐसा कर सकते हैं:

val userForm = Form(
    mapping(
    "someStringField" -> text, 
    "someIntField" -> number 
)(User.apply)(User.unapply) 
.verifying(x => SomeFunctionThatReceivesAnUserAndReturnsABoolean(x)) 

और उसके बाद मैं पूरे उपयोगकर्ता उदाहरण उपलब्ध होता सत्यापन कार्य करने के लिए पारित कर दिया। उस दृष्टिकोण के साथ समस्या यह है कि परिणामी त्रुटि someIntField फ़ील्ड से जुड़े होने के बजाय पूरे फॉर्म से जुड़ी होगी।

वहाँ पूरे फार्म के बजाय एक तरह से दोनों बातें विशिष्ट क्षेत्र मैं सत्यापित करना चाहते हैं के लिए जुड़े त्रुटि मिलती है, एक और क्षेत्र का उपयोग कर एक क्षेत्र को मान्य और बनाए रखने के लिए है?

उत्तर

0

मुझे लगता है कि वे JSR-मान्यता के लिए स्केला-कोड के नक्शे। वहां निश्चित रूप से यह संभव नहीं है। ऐसा करने के लिए कुछ तर्क हैं। मुख्य रूप से एक सत्यापन सरल होना चाहिए और जटिल तर्क नहीं बनाना चाहिए। मैं अब भी इसे कैसे याद करता हूं। Play1 से ओवल मेरे लिए बेहतर था।

+0

यह अजीब बात है। मैंने सोचा था कि एक निश्चित क्षेत्र की आवश्यकता होती है जब एक और क्षेत्र खाली नहीं था, सामान्य बात थी, और जटिल तर्क नहीं माना जाता था। इस प्रकार यह अजीब बात है कि कोई भी इससे पहले, विशेष रूप से नाटक में कूद गया है! फ्रेमवर्क निर्माता स्वयं। –

3

क्या आप समूह कर सकते हैं संबंधित पैरामीटर पैरामीटर के लिए एक उपसर्ग होने से परहेज नहीं करते हैं:

val aForm = Form(
mapping(
    "prefix" -> tuple(
    "someStringField" -> text, 
    "someIntField" -> number 
) verifying (tup => your verification) 
)(tup => User.apply(tup._1, tup._2)(User.unapply...) 

मैं सिर्फ आसपास के मानचित्रण के बिना कुछ इसी तरह का उपयोग करें। आप लागू/unapply एक छोटे से समायोजित करने और यह संकलन करने के लिए मैन्युअल रूप से तर्क पारित करने के लिए होगा।

त्रुटि "उपसर्ग" समूह के लिए पंजीकृत किया जाएगा।

मैं भी यह अजीब आप किसी भी क्षेत्र आप जब प्रपत्र की पुष्टि करने FormError का उपयोग कर करना चाहते हैं पर त्रुटियों पंजीकृत नहीं कर सकता है कि लगता है ...

+1

यह दृष्टिकोण काम नहीं करता है, क्योंकि त्रुटि "उपसर्ग" फ़ील्ड से जुड़ी होगी। मैं चाहता था कि यह "कुछ इंफिल्ड" से जुड़ा हो। जबकि मैं इसके बजाय "उपसर्ग" का उपयोग कर स्वीकार कर सकता हूं, अगर मुझे "someStringField" मान को ध्यान में रखते हुए सत्यापित करने के लिए किसी अन्य फ़ील्ड की आवश्यकता है तो समस्या फिर से वापस आ जाएगी। दोनों त्रुटियां "उपसर्ग" फ़ील्ड से जुड़ी हो जाएंगी। –

8

मैं दूसरे के मूल्य के आधार क्षेत्रों के लिए मान्यता को जोड़ने के साथ एक ही आवश्यकताओं है खेत। मुझे यकीन नहीं है कि यह idiomatic PLAY 2.2.1 में कैसे किया जाता है लेकिन मैं निम्नलिखित समाधान के साथ आया था। इस उपयोग में मैं बिल्टिन "मैपिंग" को एक साधारण प्रकार कनवर्टर में खराब कर रहा हूं और "validateForm" विधि में अपना "उन्नत इंटर फ़ील्ड" सत्यापन लागू करता हूं। मानचित्रण:

val userForm = Form(
mapping(
    "id" -> optional(longNumber), 
    "surename" -> text, 
    "forename" -> text, 
    "username" -> text, 
    "age" -> number 
)(User.apply)(User.unapply) 
) 

private def validateForm(form:Form[User]) = { 
    if(form("username").value.get == "tom" || form("age").value.get == "38") { 
    form 
     .withError("forename", "tom - forename error") 
     .withError("surename", "tom - surename error") 
    } 
    else 
    form 
} 

def update = Action { implicit request => 
    userForm.bindFromRequest.fold({ 
    formWithErrors => BadRequest(users.edit(validateForm(formWithErrors))) 
    }, { user => 
    val theForm = validateForm(userForm.fill(user)) 
    if(theForm.hasErrors) { 
     BadRequest(users.edit(theForm)) 
    } else { 
     Users.update(user) 
     Redirect(routes.UsersController.index).flashing("notice" -> s"${user.forename} updated!") 
    } 
    }) 
} 

यहां तक ​​कि यह मैं काम करता है तत्काल एक अधिक मुहावरेदार संस्करण के लिए खोज हालांकि ...

संपादित करें: मुहावरेदार नाटक में एक कस्टम play.api.data.format.Formatter उपयोग , http://workwithplay.com/blog/2013/07/10/advanced-forms-techniques/ पर और इससे आपको प्रोग्राम में रूप रूप से त्रुटियों को जोड़ने की सुविधा मिलती है।, टॉम Myer को

mapping(
[...] 
    "username" -> of(usernameFormatter), 
[....] 
+1

अभी भी मेरे लिए बेवकूफ महसूस नहीं कर रहा है ... यह लंबे समय से मैंने यह सवाल किया है, और तब से, मैं स्कैला के लिए अपने स्वयं के सत्यापन ढांचे पर काम कर रहा हूं https://github.com/NovaMage/SValidator । कार्यान्वयन लगभग समाप्त हो गया है लेकिन यह अभी तक अच्छी तरह से प्रलेखित नहीं है। हालांकि इसमें यूनिट परीक्षणों का पूरा सूट है। एक बार जब मैं इसका उपयोग कैसे करें और इसे खेलने के साथ एकीकृत करने के बारे में प्रलेखन पूरा कर लेता हूं, तो मैं इसे यहां एक उत्तर के रूप में पोस्ट करूंगा :) –

1

धन्यवाद यहाँ मैं

class MatchConstraint[A](val targetField:String, val map:(String, Map[String, String]) => A, val unmap:A => String) extends Formatter[A] { 
    override def bind(key: String, data: Map[String, String]): Either[Seq[FormError], A] = { 
    val first = data.getOrElse(key, "") 
    val second = data.getOrElse(targetField, "") 
    if (first == "" || !first.equals(second)) { 
     Left(List(FormError(key, "Not Match!"))) 
    } 
    else { 
     Right(map(key, data)) 
    } 
    } 

    override def unbind(key: String, value: A): Map[String, String] = Map(key -> unmap(value)) 
} 

और यहाँ क्या इस्तेमाल किया मेरी प्रपत्र देखो क्या:

val usernameFormatter = new Formatter[String] { 

override def bind(key: String, data: Map[String, String]): Either[Seq[FormError], String] = { 
    // "data" lets you access all form data values 
    val age = data.get("age").get 
    val username = data.get("username").get 
    if(age == "66") { 
    Left(List(FormError("username", "invalid"), FormError("forename", "invalid"))) 
    } else { 
    Right(username) 
    } 
} 

override def unbind(key: String, value: String): Map[String, String] = { 
    Map(key -> value) 
} 
} 
} 

इस तरह प्रपत्र मानचित्रण में पंजीकरण दिनांक: मेरे फ़ॉर्मेटर इस तरह दिखता है

val registerForm = Form(
    mapping(
    "email" -> email.verifying(minLength(6)), 
    "password" -> text(minLength = 6), 
    "passwordConfirmation" -> of(new MatchConstraint[String]("password", (key, data) => data.getOrElse(key, ""), str => str)) 
)(RegisterData.apply)(RegisterData.unapply) 
) 
0

दस्तावेज में:, val userFormConstraintsAdHoc = Form( mapping( "name" -> text, "age" -> number )(UserData.apply)(UserData.unapply) verifying("Failed form constraints!", fields => fields match { case userData => validate(userData.name, userData.age).isDefined }) )

मुख्य रूप से सिर्फ unapply के बाद सत्यापित करने और आप सभी क्षेत्रों मैप किया गया है ताकि आप एक अधिक पूर्ण सत्यापन कर सकते हैं: Playframework Documentation

आप नीचे दिए गए कोड देख सकते हैं।

5

मुझे विश्वास है कि आप जो खोज रहे हैं वह play.api.data.validation.Constraint है।

आप पूर्वनिर्धारित cities की एक सूची और एक otherCity क्षेत्र के साथ एक RegisterForm है और आप या तो cities या otherCity आपूर्ति किए जाने, यानी, otherCity सत्यापित की जानी चाहिए अगर cities प्रदान नहीं की है जरूरत है कहते हैं:

case class RegisterForm(
    email: String, 
    password: String, 
    cities: Option[List[String]], 
    otherCity: Option[String] 
) 

आप इस के चारों ओर एक कस्टम Constraint लिख सकते हैं:

val citiesCheckConstraint: Constraint[RegisterForm] = Constraint("constraints.citiescheck")({ 
    registerForm => 
    // you have access to all the fields in the form here and can 
    // write complex logic here 
    if (registerForm.cities.isDefined || registerForm.otherCity.isDefined) { 
     Valid 
    } else { 
     Invalid(Seq(ValidationError("City must be selected"))) 
    } 
}) 

और अपने प्रपत्र परिभाषा हो जाता है:

val registerForm = Form(
    mapping(
    "email" -> nonEmptyText.verifying(emailCheckConstraint), 
    "password" -> nonEmptyText.verifying(passwordCheckConstraint), 
    "cities" -> optional(list(text)), 
    "other_city" -> optional(text) 
)(RegisterForm.apply)(RegisterForm.unapply).verifying(citiesCheckConstraint) 
) 

इस उदाहरण emailCheckConstraint में और passwordCheckConstraint कि मैं citiesCheckConstraint के लिए इसी तरह परिभाषित अतिरिक्त कस्टम की कमी कर रहे हैं। यह Play 2.2.x में काम करता है।

अद्यतन: प्ले 2.3.8 पर निर्माण के साथ-साथ।

+0

फिर आप विशेष फ़ील्ड के लिए त्रुटि कैसे सेट करते हैं? –