2011-11-25 14 views
11

मैं अपने Grails नियंत्रक कोड को साफ करने के तरीकों की तलाश में हूं। विभिन्न नियंत्रकों में मैं और अधिक या कम एक ही तर्क है ..Grails नियंत्रकों को और अधिक DRY बनाना?

  • वस्तु
  • जांच प्राप्त करता है, तो यह
  • आदि मौजूद ..

वहाँ नियंत्रक कार्यों बनाने के लिए एक सुझाव दिया और रास्ता नहीं है सामान्य कोड का पुन: उपयोग करें?

--- समाधान ---

सवाल का जवाब सभी समाधान हम लागू कर दिया है करने के लिए योगदान दिया है।

हमने एक कक्षा बनाई जो हमारे नियंत्रकों में मिक्सिन दृष्टिकोण का उपयोग करके उपयोग की जाती है। मिक्सिन का खुलासा करने वाली विधियों में से एक ऑब्जेक्ट विधि के साथ है। यह विधि नियंत्रक से डोमेन नाम लेती है और विधि के लिए इसका आधार उपयोग करती है। इस व्यवहार को निश्चित रूप से ओवरराइड किया जा सकता है!

def withObject(object=this.getClass().getName()-"Controller", id="id", Closure c) { 
    assert object 
    def obj = grailsApplication.classLoader.loadClass(object).get(params[id]) 
    if(obj) { 
     c.call obj 
    } else { 
     flash.message = "The object was not found" 
     redirect action: "list" 
    } 
} 

तो सभी उत्तरों ने समाधान में योगदान दिया है! आपका बहुत बहुत धन्यवाद!

+4

कृपया प्रश्न संपादित करें और अपने कोड का एक उदाहरण जोड़ें। फिलहाल सवाल बहुत अस्पष्ट है। – ordnungswidrig

उत्तर

8

मैं हमेशा इस ब्लॉग पोस्ट बाहर खींच जब यह सवाल आता है:

http://mrpaulwoods.wordpress.com/2011/01/23/a-pattern-to-simplify-grails-controllers/

मूल रूप से आप अपने नियंत्रकों में विभिन्न डोमेन के लिए एक निजी सहायक है।

private def withPerson(id="id", Closure c) { 
    def person = Person.get(params[id]) 
    if(person) { 
     c.call person 
    } else { 
     flash.message = "The person was not found." 
     redirect action:"list" 
    } 
} 

जिस तरह से आप गेटर कोड बहुत लचीला है और मेरे लिए एक विशिष्ट प्रयोग (कि ब्लॉग में शामिल नहीं है) संपादन आदि के लिए है

मैं सामान्य रूप से कोड इस तरह से (मैं अपनी स्पष्ट विभाजन और पठनीयता के लिए पैटर्न की तरह):

def editIssue() { 
    withIssue { Issue issue -> 
     def issueTypes = IssueTypeEnum.values().collect {it.text } 
     [issueTypes:issueTypes,activePage:"issue", issue: issue] 
    } 
} 

def doEditIssue(IssueCommand cmd) { 
    if(cmd.validate()) { 
     withIssue { Issue issue -> 
      issue.updateIssue(cmd) 
      redirect(action: "show", id: issue.id) 
     } 
    } 
    else { 
     def issueTypes = IssueTypeEnum.values().collect {it.text } 
     render(view: "edit", model:[issueTypes:issueTypes,issue:cmd,activePage:"issue"]) 
    } 
} 
मेरी गेटर सहायक जा रहा है के साथ

:

private def withIssue(Closure c) { 
    def issue = Issue.get(params.id) 
    if(issue) { 
     c.call issue 
    } 
    else { 
     response.sendError(404) 
    } 
} 

मुझे लगता है कि है कि mixin विधि ('एक सामान्य अमूर्त नियंत्रक' मार्ग के समान) बहुत अच्छा है, लेकिन इस तरह से दो फायदे हैं:

  1. आप सहायक टाइप कर सकते हैं, जैसा कि आप देखते हैं कि मैं आपको एसटीएस/आईडीईए (नेटबीन्स का परीक्षण नहीं किया गया) में विधियों आदि तक पहुंच प्रदान करता हूं,
  2. पुनरावृत्ति बहुत अधिक नहीं है, और गेटर बदलने की क्षमता (इसके लिए उपयोग करने के लिए उदाहरण BarDomain.findByFoo (params.id) आदि)

दृश्य मैं संपादित करने के लिए बाध्य में() मैं सिर्फ <g:form> में एक id="${issue.id}" रख दिया और यह सहजता से चलता है।

+0

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

0

सामान्य तरीकों के साथ अमूर्त नियंत्रक को लागू करें ('संरक्षित' निर्देश का उपयोग करें) और इसे अपने वास्तविक नियंत्रकों से बढ़ाएं। इस विधि के नाम की शुरुआत में 'get' और 'set' शब्दों का उपयोग न करें। अच्छा नहीं है, लेकिन यह काम करता है।

+1

आप इस विधि के नाम की शुरुआत में 'get' और 'set' शब्दों का उपयोग न करने का सुझाव क्यों देते हैं? – gotomanners

+0

उन्हें 'गेटर' या 'सेटर' के रूप में पहचानने से बचने के लिए। – jenk

6

मैं इसके लिए विरासत की अनुशंसा नहीं करता, क्योंकि आप कई सुपर कक्षाओं में सामान्य तरीकों को फैल नहीं सकते हैं। यदि आपके पास कई नियंत्रक हैं तो आपकी अमूर्त कक्षा जल्दी गन्दा हो जाएगी। आप संरचना का उपयोग नहीं कर सकते (उदाहरण के लिए सेवा का उपयोग कर) क्योंकि आपके पास response, render, या params तक सीधे पहुंच नहीं है।

मैं जिस दृष्टिकोण का उपयोग करता हूं वह मिक्सिन के माध्यम से सामान्य तरीकों को इंजेक्ट करना है।

@Mixin(ControllerGenericActions) 
@Mixin(ControllerUtil) 
class BookController { 
    def show = &genericShow.curry(Book) 

    def exists = { 
    render(idExists(Book)) 
    } 
} 

पहली कार्रवाई showControllerGenericActions.groovy में एक सामान्य विधि का उपयोग करता, एक तर्क यह से आबद्ध साथ। एक mixin idExists विधि का दूसरा उपयोग एक नियंत्रक कार्रवाई के अंदर है।

यहाँ इस मामले में के लिए src/groovy/ControllerGenericActions.groovy

class ControllerGeneric { 
    def genericShow(Class clazz) { 
    render clazz.get(params.id) as XML 
    } 
} 

एक उदाहरण कोड और src/groovy/ControllerUtil.groovy

class ControllerUtil { 
    def idExists (Class clazz) { 
    return clazz.get(params.id) != null 
    } 

कोई बहुत उपयोगी में है, लेकिन आप विचार मिलता है।

+0

मैं वास्तव में बंद होने के उपयोग में नहीं हूं, इसलिए अगर मैं गलती कर रहा हूं तो कृपया क्षमा करें। लेकिन यदि 'जेनेरिकशो (क्लास क्लैज)' जैसी कोई विधि बनाई गई है, तो क्या आप उस विधि को करी कर सकते हैं? मैं हमेशा इस धारणा में था कि एक विधि को घुमाया नहीं जा सकता है लेकिन एक बंद कर सकते हैं। – Marco

+0

विधि नाम का उपयोग करने से पहले इसका कारण है: यह एक विधि को बंद करने में बदल देता है। – Antoine

+0

मुझे इस समाधान पर एक प्रश्न है: क्या कंट्रोलर जेनरिक मिक्सिन यूनिट टेस्टेबल है? मैं पूछता हूं क्योंकि 'रेंडर' Grails द्वारा प्रदान की गई एक विधि है जबकि नियंत्रकों को बढ़ाते हुए –

संबंधित मुद्दे