रेल ट्यूटोरियल समाप्त करने और अपना ऐप शुरू करने के बाद, चीजें भ्रमित हो जाती हैं। जैसे आपका गैर-सीआरयूडी, सामान्य तर्क कहां जाता है? ट्विटर से फॉलोअर्स को हथियाना MVC में कैसे फिट होता है? दो लोगों से पूछो, और आपको चार उत्तर मिलते हैं। या आपका धागा स्मार्ट लोगों के झुंड में बदल जाता है, जो घंटों एक-दूसरे का अपमान करते हैं, जबकि आप डेस्क के खिलाफ अपना सिर पीटते हैं। किसी भी तरह, आपको सिरदर्द हो गया है।
आप उस ऐप का निर्माण नहीं कर सकते जिसका आप सपना देख रहे हैं कुछ . के बिना सामान्य, गैर-रेल तर्क। तो आप अपना कोड कहां रखते हैं, और फिर भी चीजों को सरल रखते हैं?
शुरू करने का आसान स्थान
जब मेरे पास तर्क है जो किसी मौजूदा ActiveRecord मॉडल से संबंधित लगता है, तो मैं इसे उस मॉडल में डालकर शुरू करूंगा। उदाहरण के लिए, अगर मेरे पास Game
था मॉडल और मैं सीएसवी फाइलों से गेम का एक गुच्छा आयात करना चाहता था, मैं उस विधि को सीधे Game
पर रखूंगा कक्षा:
class Game < ActiveRecord::Base
def self.parse_from_csv(csv_string)
games = []
CSV.parse(csv_string, quote_char: "'") do |row|
games << Game.from_csv_row(row) if (row[0] == 'G')
end
games
end
def self.from_csv_row(row)
Game.new({
dgs_game_id: row[1],
opponent_name: row[2],
created_at: row[4],
updated_at: row[4],
})
end
end
आपके पास वह सारी जानकारी है जो आपके तरीकों को सही हाथ में चाहिए। यह आसानी से परीक्षण योग्य है। और शायद यही वह जगह है जहां एक नया योगदानकर्ता पहले उस तर्क की तलाश करेगा।
लेकिन अगर आप उस मॉडल को जोड़ते और बदलते रहते हैं, तो यह बड़ा और जटिल हो जाएगा। मॉडल के विभिन्न भाग अजीब तरीके से बातचीत करेंगे। जितना अधिक आप इसे बदलेंगे, इसे बदलना उतना ही कठिन होगा।
उस स्थिति में, आप शायद उस कोड को एक गैर-ActiveRecord मॉडल में पुन:सक्रिय करना चाहेंगे।
गैर-ActiveRecord मॉडल
सिर्फ इसलिए कि यह एक रेल ऐप में है, इसका मतलब यह नहीं है कि इसे एक्टिव/एक्शन-जो कुछ भी विरासत में मिला है।
आप अपने रूबी कोड को सादे रूबी ऑब्जेक्ट में लिख सकते हैं, और उन्हें अपने Rails ऐप में उपयोग कर सकते हैं। इन वस्तुओं को अभी भी मॉडल कहा जा सकता है, क्योंकि वे मॉडलिंग आपकी समस्या का हिस्सा हैं। उनके पास अपना डेटा संग्रहीत करने वाला ActiveRecord डेटाबेस नहीं है।
अगली बार जब मैंने उस गेम CSV पार्सर पर काम किया, तो Game
क्लास कुछ ज्यादा ही बड़ी हो रही थी। इसलिए मैंने पार्सर लॉजिक को उसके अपने GameCSVParser
. में स्थानांतरित कर दिया कक्षा।
पूरी प्रतिबद्धता यहाँ है, लेकिन गैर-ActiveRecord वर्ग इस तरह दिखता है:
class GameCSVParser
def initialize(csv_string)
@rows = CSV.parse(csv_string, quote_char: "'")
end
def games
game_rows.map { |row| Game.new(game_attributes(row)) }
end
private
def game_rows
@rows.select { |row| is_game_row?(row) }
end
def game_attributes(row)
{
dgs_game_id: row[1],
opponent_name: row[2],
created_at: row[4],
updated_at: row[4],
}
end
def is_game_row?(row)
row[0] == 'G'
end
end
यदि मैं जो तर्क जोड़ रहा हूं वह किसी विशिष्ट ActiveRecord मॉडल से संबंधित नहीं है, तो मैं एक नया सादा रूबी ऑब्जेक्ट बनाने के लिए सही हूं। या अगर कोड ऐसा लगता है कि यह उस चीज़ का हिस्सा होना चाहिए जो अभी तक ऐप में मौजूद नहीं है। अन्यथा, वे ज्यादातर रिफैक्टरिंग के माध्यम से पॉप अप करते हैं।
सादे रूबी वस्तुओं के साथ, आप कुछ भी लिख सकते हैं। लेकिन यह जानकर कि आप कुछ भी लिख सकते हैं दिशा में मदद नहीं करता है। आपको किन तरीकों की ज़रूरत है? आपके सभी नए ऑब्जेक्ट कैसे इंटरैक्ट करेंगे?
बहुत सारे रेल ऐप्स समान श्रेणियों का उपयोग करते हैं सादे रूबी वस्तुओं की। ये श्रेणियां ऐसे पैटर्न हैं जिनका अनुसरण आप कोड लिखने के लिए कर सकते हैं जिन्हें अन्य डेवलपर पहचानेंगे। आपने उनमें से कुछ के बारे में पहले ही सुना होगा।
सेवा ऑब्जेक्ट, प्रस्तुतकर्ता, और कार्य
सेवा वस्तुओं, प्रस्तुतकर्ताओं और नौकरियों के बारे में कुछ खास नहीं है। वे केवल सादे रूबी ऑब्जेक्ट हैं जो एक विशेष पहचानने योग्य तरीके से कार्य करते हैं।
उदाहरण के लिए, एक अनुरोध कार्य एक सादा रूबी वर्ग है जिसमें perform
. है विधि और एक @queue
:
class FetchGamesForPlayer
@queue = :default
def self.perform(player_id)
player = Player.scoped_by_id(player_id).ready_for_fetching.first
player && player.fetch_new_games!
end
end
perform
कार्य चलने पर कॉल किया जाता है।
एक प्रस्तुतकर्ता कोड के साथ एक सादा रूबी ऑब्जेक्ट है जो केवल एक दृश्य के अंदर समझ में आता है:
class UserPresenter
def show_related_users?
@user.related.count > 3
end
end
इसमें रेल के व्यू हेल्पर्स भी शामिल हो सकते हैं, या कुछ अलग ऑब्जेक्ट ले सकते हैं और दृश्य की सुविधा के लिए उन्हें एक एकीकृत ऑब्जेक्ट के रूप में मान सकते हैं।
एक सेवा वस्तु एक सादा रूबी ऑब्जेक्ट है जो उस प्रक्रिया का प्रतिनिधित्व करता है जिसे आप करना चाहते हैं। उदाहरण के लिए, किसी पोस्ट पर टिप्पणी लिखने से:
- टिप्पणी छोड़ें।
- पोस्ट के लेखक को एक सूचना मेल भेजें।
एक सेवा वस्तु दोनों कर सकती है, और उस तर्क को आपके नियंत्रक से बाहर रख सकती है।
यहां सेवा वस्तुओं पर बहुत अच्छा प्रभाव पड़ता है। यह उदाहरणों से भरा है।
साधारण प्रक्रियाओं के लिए, मैं सेवा वस्तुओं से परेशान नहीं हूं। लेकिन अगर नियंत्रक बहुत भारी होने लगे, तो वे उस अतिरिक्त तर्क को रखने के लिए एक अच्छी जगह हैं।
आप अपने स्वयं के व्यावसायिक तर्क को व्यवस्थित करने के लिए इन प्रतिमानों का उपयोग कर सकते हैं। वे केवल रूबी ऑब्जेक्ट हैं, लेकिन वे रूबी ऑब्जेक्ट हैं जो एक निश्चित स्वाद साझा करते हैं, जिसका एक नाम होता है, और जिसके बारे में आप अन्य डेवलपर्स से बात कर सकते हैं।
आप कहां से शुरू करते हैं?
आपके गैर-रेल व्यावसायिक तर्क कई अलग-अलग स्थानों पर जा सकते हैं। चुनना मुश्किल हो सकता है। तो मैं यहाँ क्या करता हूँ:
- यदि तर्क ज्यादातर मौजूदा वर्ग से संबंधित है, भले ही यह एक ActiveRecord मॉडल है, मैं इसे उस वर्ग में रखता हूं।
- यदि यह किसी मौजूदा वर्ग के लिए उपयुक्त नहीं है, तो मैं तर्क रखने के लिए एक नया सादा रूबी वर्ग बनाता हूं।
- अगर ऐसा लगता है कि तर्क किसी ऐसी चीज का हिस्सा होना चाहिए जो अभी तक अस्तित्व में नहीं है, तो मैं इसके लिए एक नया सादा रूबी वर्ग बना देता हूं।
- यदि मैं बाद में कोड पर वापस आता हूं, और मॉडल बहुत जटिल हो रहा है, या उस मॉडल में अब कोड का कोई मतलब नहीं है, तो मैं इसे अपने स्वयं के सादे रूबी वर्ग में पुन:सक्रिय कर दूंगा।
- यदि कोड केवल एक दृश्य में समझ में आता है, तो मैं इसे एक सहायक में जोड़ दूंगा या एक प्रस्तुतकर्ता बनाऊंगा।
- यदि कोड को HTTP अनुरोध के दौरान चलाने की आवश्यकता नहीं है, या पृष्ठभूमि में चलाना है, तो यह एक काम में चला जाता है।
- अगर मैं कई अलग-अलग मॉडल या प्रक्रिया के चरणों को जोड़ रहा हूं, और यह नियंत्रक को समझने में बहुत कठिन बना रहा है, तो मैं इसे एक सेवा ऑब्जेक्ट में डाल दूंगा।
आप कैसे हैं? आपका कोड कहां जाता है? और क्या आपके पास इनके अलावा कोई पैटर्न है जो आपको मददगार लगा? एक टिप्पणी छोड़ें और मुझे बताएं।
और अगर आपके पास अभी तक कोई प्रक्रिया नहीं है, तो मेरा प्रयास करें। देखें कि यह आप पर कैसे फिट बैठता है। कोड लिखने का कोई सही तरीका नहीं है, लेकिन जब आप अटक जाते हैं, तो इस तरह की प्रक्रिया आपको आरंभ करने में मदद करेगी।