रेल-आधारित विश्राम प्रदाता: विचारों के साथ एक बुरा सपना

ब्राउज़र-आधारित MVC फ्रेमवर्क के विकास के साथ, RAIL प्रदाताओं के लिए सुविधाजनक फ्रेमवर्क के संदर्भ में रेल का अक्सर उल्लेख किया गया है। हम इस उद्देश्य के लिए और लंबे समय तक रेल का उपयोग करते हैं। हालाँकि, एक बहुत बड़ी समस्या है: विचार। प्रतिक्रिया के लिए JSON संरचना का वर्णन करने वाले दृश्य।

पहली नज़र में, सब कुछ ठीक है। कुछ जटिल मामलों में .to_json या RABL के .to_json कुछ नहीं चाहिए। लेकिन तब स्थिति नियंत्रण से बाहर हो जाती है। और बेहतर जीवन की तलाश में JSON बिल्डरों के माध्यम से खोज के अंतहीन चक्र हैं।

समस्या


आइए बैंकिंग सेवा को एक उदाहरण के रूप में लेते हैं। इसमें 30 मॉडल शामिल हैं। प्रत्येक मॉडल एक CRUD संसाधन (प्रत्येक 3-4 विस्तार विधियों के साथ) द्वारा दर्शाया गया है। प्रत्येक मॉडल में 10-12 फ़ील्ड होते हैं और ये आमतौर पर लंबी लाइनें होती हैं। और, ज़ाहिर है, वे सभी जुड़े हुए हैं। 4-5 के स्तर belongs_to स्तर है।

यह याद रखना महत्वपूर्ण है कि वास्तविक जीवन में, JSON प्रतिक्रिया केवल मॉडल संरचना का प्रत्यक्ष डंप नहीं है। यह लगातार परिस्थितियों का सामना करता है (जो विशेषता को उत्तर में शामिल किया जाना चाहिए? एक और विशेषता पर निर्भर करता है) और कस्टम तरीके।

अभ्यावेदन की समस्या यह है कि REST सेवा के क्लाइंट को ऐसे प्रत्येक मॉडल के लिए मॉडल फ़ील्ड का एक अनूठा सेट चाहिए और इस REST संसाधन के प्रत्येक मेथड _ के लिए। और नेस्टेड संस्थाओं के बारे में मत भूलना।


कल्पना कीजिए कि आपके पास प्रत्येक मॉडल के लिए 4-5 फ़ील्ड हैं। और यह सिर्फ शुरुआत है। उसके बाद, मॉडल में एक और शामिल है। और माता-पिता केवल 3 छोटे क्षेत्रों को देखना चाहते हैं जो पूरी तरह से उनके रिश्ते का वर्णन करते हैं। और फिर इसी मॉडल में एक और माता-पिता शामिल हैं जिन्हें 2 अन्य क्षेत्रों की आवश्यकता है। यह लगभग 10 अलग-अलग सेट हैं। और इस तरह के प्रत्येक सेट में अभी भी अतिरिक्त शर्तें हो सकती हैं कि मॉडल अपने आप में क्या निवेश करता है।

दर्द


इसका समाधान हमने आरएबीएल के साथ शुरू किया। सबसे पहले यह काफी प्रभावी दिखता है, लेकिन व्यवहार में यह जटिल अभ्यावेदन के लिए पूरी तरह से अनुपयुक्त है। वास्तव में, RABL .to_json से इतनी दूर नहीं गया है। हमने कई अलग-अलग बिल्डरों की कोशिश की और आखिरकार जिबॉल्डर मणि पर बस गए, जो आपको सिंटैक्स शोर से बचने के लिए बेहद सरल और सरल कोड लिखने की अनुमति देता है।

लेकिन इससे कोई फायदा नहीं हुआ। कोड को डुप्लिकेट नहीं करने के लिए हम अभ्यावेदन में क्या करते हैं? हम पार्सल का उपयोग करते हैं, सही। बहुत जल्द, इसने हमें प्रत्येक मॉडल के लिए 10-15 पार्शलों का नेतृत्व किया। इसे 30 मॉडलों से गुणा करने पर हमें app/views में 450 फाइलें मिलती app/views । यह गुच्छा बनाए रखने के लिए बस असंभव है।

प्रस्तुतकर्ता पैटर्न


इस तरह की समस्याओं को हल करने के लिए एक प्रसिद्ध दृष्टिकोण प्रस्तुतकर्ता पैटर्न है। चूंकि हमारे विचार केवल रूबी कोड हैं, इसलिए तार्किक पहला कदम इसे कक्षाओं में लपेटना था।

 # example taken from http://quickleft.com/blog/presenters-as-a-solution-to-asjson-woes-in-rails-apis class Api::V1::ResourcePresenter attr_reader :resource def initialize( resource ) @resource = resource end def as_json( include_root = false ) data_hash = { :attr1 => @resource.attr1, :attr2 => @resource.attr2 } data_hash = { :resource => data_hash } if include_root data_hash end end 


इसने आने वाली मापदंडों के साथ एक विधि में फ़ाइलों और समूह के समान सेटों की संख्या को कम करना संभव बना दिया।

बहुत बढ़िया। हम मॉडल फ़ील्ड के सेटों का वर्णन करने वाले सज्जाकार के लिए 1 से 1 के अनुपात में पहुंचे। लेकिन अब एक और समस्या पैदा हो गई है: यह कोड वैसा नहीं है जैसा रेल से अपेक्षित है।

सबसे अच्छा परिणाम आपको मणि ड्रेपर प्राप्त करने की अनुमति देता है। इसके साथ, हम उपरोक्त कोड को इस में बदल सकते हैं:

 # app/decorators/article_decorator.rb class ArticleDecorator < ApplicationDecorator decorates :article def the_very_important_fields_set( include_root = false ) data_hash = { :attr1 => att1, :attr2 => attr2 } data_hash = { :resource => data_hash } if include_root data_hash end end 


लेकिन समस्याएं खत्म नहीं हुईं, अब चेहरे पर DRY का स्पष्ट उल्लंघन है। बड़ी संख्या में फ़ील्ड्स के साथ, हम कुंजियों में समान पंक्तियों वाले विशाल हैश पर अटक जाते हैं :foo और self.foo मान।

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

इस लेखन के समय, जब आप उत्पन्न करते हैं, तो Jbuilder आपको कच्चे JSON तार डालने की अनुमति नहीं देता है। हालांकि, एक और दृष्टिकोण है जो वांछित परिणाम प्राप्त करने में मदद कर सकता है। एक उत्कृष्ट कांटा है (पुल-रिक्वेस्ट पहले से ही लेखक द्वारा आंशिक रूप से पुष्टि की जा चुकी है और यह कार्यक्षमता बहुत जल्द ही जौल्डर में गिर जाएगी)।

इस कांटे के साथ, हम अपने कोड को इस प्रकार संशोधित कर सकते हैं:

 # app/decorators/article_decorator.rb class ArticleDecorator < ApplicationDecorator decorates :article def the_very_important_fields_set( include_root = false ) data = Jbuilder.encode do |j| j.(self, :attr1, :attr2) end data = { :resource => data } if include_root end def another_set Jbuilder.encode do |j| j.(self, :attr1, :attr2, :attr3) j.cards card.basic_fields(:include_transactions) end end end 


यह सबसे अच्छा उदाहरण नहीं हो सकता है, लेकिन अभ्यास से पता चला है कि इस तरह से जूलर का उपयोग करना बड़े सज्जाकारों को बहुत सरल करता है।

परिणामस्वरूप, हमारे पास निम्नलिखित संरचना है:



इस तरह की रणनीति थोड़ी बेमानी लग सकती है। लेकिन यह बड़ी डेटा परतों के लिए बहुत अच्छी तरह से काम करता है। यह रणनीति REST प्रदाताओं को सटीक होने देती है (प्रत्येक अनुरोध के लिए एक विशेष विधि की आवश्यकता वाले फ़ील्ड का सेट दें), दोहराव से बचें, और समर्थन की सादगी रखें।

सुरक्षा के बारे में पी.एस.


ऐसा लगता है कि यह रणनीति विभिन्न क्षेत्रों के लिए विभिन्न भूमिकाओं के वितरण की समस्या को भी हल करती है। और यह वास्तव में है। हालांकि, यह आमतौर पर करने योग्य नहीं है - यह तर्क का दोहराव पैदा कर सकता है। हमें न केवल डेटा के वितरण को अधिकृत करने की आवश्यकता है, बल्कि एक बदलाव भी है।

जब तक हम इस रणनीति में आए, तब तक हमारे पास पहले से ही उत्कृष्ट हेमलाड्र मणि थी, जो हमें इस समस्या को बेहतर ढंग से हल करने की अनुमति देता है। लेकिन यह पूरी तरह से अलग लेख के लिए एक विषय है :)।

Source: https://habr.com/ru/post/In140633/


All Articles