data binding - Grails कमांड ऑब्जेक्ट डेटा बाध्यकारी




data-binding groovy (3)

क्या आपको वास्तव में विशेषता प्रकार और उत्पाद प्रकार गुणों के लिए उप-आदेश होने की आवश्यकता है? किसी भी कारण से आप PropertyEditorSupport बाध्यकारी का उपयोग नहीं कर रहे हैं? उदाहरण के लिए:

public class ProductTypeEditor extends PropertyEditorSupport
{
    ProductAdminService productAdminService // inject somewhow
    void setAsText(String s)
    {
        if (s) value = productAdminService.productTypes.find { it.id == s.toLong() }
    }

    public String getAsText()
    {
        value?.id        
    }
}

(और विशेषता टाइप टाइप ऑब्जेक्ट के लिए कुछ समान), और इन्हें एक संपादक रजिस्ट्रार में पंजीकृत करें:

import java.beans.PropertyEditorSupport
public class CustomEditorRegistrar implements PropertyEditorRegistrar {
    public void registerCustomEditors(PropertyEditorRegistry reg) {
        reg.registerCustomEditor(ProductType, new ProductTypeEditor())
        reg.registerCustomEditor(AttributeType, new AttributeTypeEditor())
    }
}

और अपने संसाधनों में पंजीकरण करें.groovy:

beans =
{
    customEditorRegistrar(CustomEditorRegistrar)
}

फिर आपके सीएमडी में आपके पास अभी है:

class ProductCommand {
    String name
    List<AttributeType> attributeTypes = []
    ProductType productType
}

यदि आपको वास्तविक सब-कमांड एसोसिएशन की आवश्यकता है तो मैंने @ एंड्रे स्टींग्रेस ने सुझाव दिया है कि संपत्ति एडिटर समर्थन के साथ संयोजन में कुछ ऐसा किया गया है:

// parent cmd
import org.apache.commons.collections.ListUtils
import org.apache.commons.collections.FactoryUtils
public class DefineItemConstraintsCmd implements Serializable
{
    List allItemConstraints = ListUtils.lazyList([], FactoryUtils.instantiateFactory(ItemConstraintsCmd))
    //...
}    
// sub cmd
@Validateable
class ItemConstraintsCmd implements Serializable
{
    Item item // this has an ItemEditor for binding
    //...
}

उम्मीद है कि मैंने जो कुछ हासिल करने की कोशिश कर रहे हैं उसे गलत समझा नहीं है :)

डोमेन ऑब्जेक्ट और उसके एसोसिएशन को अनुरोध पैरामीटर बाध्य करने के लिए Grails का बहुत अच्छा समर्थन है । यह काफी हद तक अनुरोध पैरामीटर का पता लगाने पर निर्भर करता है जो .id साथ समाप्त होता है और डेटाबेस से स्वचालित रूप से लोड हो जाता है।

हालांकि, यह स्पष्ट नहीं है कि कमांड ऑब्जेक्ट के एसोसिएशन को कैसे पॉप्युलेट करना है। निम्नलिखित उदाहरण लें:

class ProductCommand {

    String name
    Collection<AttributeTypeCommand> attributeTypes 
    ProductTypeCommand productType
}

इस ऑब्जेक्ट में ProductTypeCommand के साथ एक सिंगल-एंडेड एसोसिएशन है और AttributeTypeCommand के साथ कई- ProductTypeCommand सहयोग है। इस विशेषता के कार्यान्वयन से सभी विशेषता प्रकारों और उत्पाद प्रकारों की सूची उपलब्ध है

interface ProductAdminService {
    Collection<AttributeTypeCommand> listAttributeTypes();
    Collection<ProductTypeCommand> getProductTypes();
}

मैं इस इंटरफेस का उपयोग जीएसपी में उत्पाद और विशेषता प्रकार चयन सूचियों को पॉप्युलेट करने के लिए करता हूं। मैं भी निर्भरता-कमांड ऑब्जेक्ट में इस इंटरफेस को इंजेक्ट करता हूं, और इसे "अनुकरण" करने के लिए उपयोग करता हूं टाइप और productType कमांड ऑब्जेक्ट पर गुण टाइप करें

class ProductCommand {

    ProductAdminService productAdminService

    String name   

    List<Integer> attributeTypeIds = []
    Integer productTypeId

    void setProductType(ProductTypeCommand productType) {
        this.productTypeId = productType.id
    }

    ProductTypeCommand getProductType() {
        productAdminService.productTypes.find {it.id == productTypeId}        
    }

    Collection<AttributeTypeCommand> getAttributeTypes() {

        attributeTypeIds.collect {id ->
            productAdminService.getAttributeType(id)
        }
    }

    void setAttributeTypes(Collection<AttributeTypeCommand> attributeTypes) {
        this.attributeTypeIds = attributeTypes.collect {it.id}
    }
}

वास्तव में क्या होता है कि attributeTypeIds और productTypeId गुण प्रासंगिक अनुरोध पैरामीटर और गेटर्स / सेटर्स "अनुकरण" productType और attributeTypes गुणों से बंधे होते हैं। क्या कमांड ऑब्जेक्ट के एसोसिएशन को पॉप्युलेट करने का कोई आसान तरीका है?


मुझे नेस्टेड कमांड ऑब्जेक्ट्स के साथ एक ही समस्या का सामना करना पड़ा है, इसलिए मैंने निम्न कार्यवाही की है:

  1. मैंने स्पष्ट रूप से अन्य डोमेन ऑब्जेक्ट्स को मेरे नियंत्रक क्रिया के पैरामीटर के रूप में जोड़ा
  2. इसके अलावा, नेस्टेड कमांड ऑब्जेक्ट्स के लिए स्पष्ट रूप से bindData () कहा जाता है (आमतौर पर, कमांड ऑब्जेक्ट जो अन्य कमांड ऑब्जेक्ट्स को लपेटता है, उसे स्पष्ट रूप से बाध्य करने की ज़रूरत के बिना अपने डेटा को सफलतापूर्वक बांध देगा, यह आपके व्यू नामकरण सम्मेलन पर निर्भर करता है)
  3. तब मैंने उन कमांड ऑब्जेक्ट्स पर। Valalidate () को बुलाया
  4. .HasErrors () के साथ त्रुटियों की जांच के लिए इन ऑब्जेक्ट्स का उपयोग करें
  5. अपने डोमेन ऑब्जेक्ट को सहेजने के लिए, प्रत्येक नेस्टेड प्रॉपर्टी को इसके संबंधित कमांड ऑब्जेक्ट के साथ स्पष्ट रूप से असाइन करें

उदाहरण के लिए, यहां एक नमूना छद्म कोड है:

class CommandObjectBig{

    String name
    CommandObjectSmall details

    static constraints = {
      name (blank: false)
    }

}


class CommandObjectSmall{

    String address

    static constraints = {
      address (blank: false)
    }

}

नियंत्रक में:

.
.
.

def save = { CommandObjectBig cob, CommandObjectSmall cos ->

//assuming cob is bounded successfully by grails, and we only need to handle cos

bindData(cos, params.details)
cos.validate()

//then do you code logic depending on if cos or cob has errors

if(cob.hasErrors() || cos.hasErrors())
render(view: "create", model: [bigInstance: cob, smallInstance: cos])
}
else
{
 //create the Domain object using your wrapper command object, and assign its details
 //property it's value using cos command object instance, and call the save on you
 //command object and every thing should go smoothly from there
   .
   .
   .

}
.
.
.
  • उम्मीद है कि grails के भावी रिलीज इस समस्या के लिए एक फिक्स है, और शायद डेवलपर को प्रत्येक कमांड ऑब्जेक्ट को असाइन करने के लिए एक वैकल्पिक पैरा या पैराम स्कोप जोड़ने की अनुमति दे सकता है, यह उपयोगी हो सकता है :)

Grails में कमांड ऑब्जेक्ट

Grails में, कमांड ऑब्जेक्ट्स डोमेन कक्षाओं की तरह हैं, लेकिन डेटा जारी नहीं है। Grails में कमांड ऑब्जेक्ट्स का उपयोग करना डोमेन बाध्यकारी और सत्यापन करने का एक आसान तरीका है जब डोमेन ऑब्जेक्ट बनाने की आवश्यकता नहीं होती है।

सबसे पहले आपको अपनी कमांड ऑब्जेक्ट का वर्णन करना होगा। यह उसी फ़ाइल में करना ठीक है जिसमें नियंत्रक होता है जो इसका उपयोग करेगा। यदि कमांड ऑब्जेक्ट का उपयोग एक से अधिक नियंत्रक द्वारा किया जाएगा, तो इसे groovy स्रोत निर्देशिका में वर्णित करें।

कमांड ऑब्जेक्ट्स घोषित करना

@Validateable
class UserProfileInfoCO {
    String name
    String addressLine1
    String addressLine2
    String city
    String state
    String zip
    String contactNo

    static constraints = {
        name(nullable: false, blank: false)
        addressLine1(nullable: true, blank: true)
        addressLine2(nullable: true, blank: true)
        city(nullable: true, blank: true)
        state(nullable: true, blank: true)
        zip(nullable: true, blank: true, maxSize: 6, matches: "[0-9]+")
        contactNo(blank: true, nullable: true)
    }
}

कमांड ऑब्जेक्ट्स का उपयोग करना

अगली बात जो आप शायद करना चाहते हैं वह डेटा को बाध्य कर रहा है, जो कमांड ऑब्जेक्ट में आपके नियंत्रक में कार्रवाई द्वारा प्राप्त किया जा रहा है और इसे मान्य करता है।

 def updateUserProfile(UserProfileInfoCO userProfileInfo) {     
  // data binding and validation
   if (!userProfileInfo.hasErrors()) {
      //do something
   } 

}




command-objects