2010-07-27 14 views
9

लक्ष्य: एक मौजूदा सिस्टम से डेटा के रात के निर्यात के साथ डेटाबेस अद्यतन करने के लिए एक सीआरओएन कार्य (या अन्य अनुसूचित घटना) का उपयोग करना।रेल ऐप में डेटा आयात करने के लिए रेक कार्य कैसे लिखें?

सभी डेटा किसी मौजूदा सिस्टम में बनाया/अपडेट/हटा दिया गया है। वेबसाइट इस प्रणाली के साथ सीधे एकीकृत नहीं होती है, इसलिए रेल ऐप को डेटा निर्यात में दिखाई देने वाले अपडेट को प्रतिबिंबित करने की आवश्यकता होती है।

मुझे लगता है कि इस तरह दिखता है ~ 5000 उत्पादों की एक .txt फ़ाइल है:

"1234":"product name":"attr 1":"attr 2":"ABC Manufacturing":"2222" 
"A134":"another product":"attr 1":"attr 2":"Foobar World":"2447" 
... 

सभी मान दोहरे उद्धरण चिह्नों (") कि कोलन (:)

फील्ड्स हैं द्वारा अलग किया जाता में संलग्न तार कर रहे हैं :

  • id: अद्वितीय आईडी; अल्फान्यूमेरिक
  • name: उत्पाद का नाम; कोई भी चरित्र
  • गुण कॉलम: तार; कोई भी चरित्र (उदाहरण के लिए, आकार, वजन, रंग, आयाम)
  • vendor_name: स्ट्रिंग; कोई भी चरित्र
  • vendor_id: अद्वितीय विक्रेता आईडी; संख्यात्मक

वर्तमान प्रणाली में विक्रेता जानकारी सामान्य नहीं है।

यहां सर्वोत्तम अभ्यास क्या हैं? क्या उत्पादों और विक्रेताओं की तालिकाओं को हटाना ठीक है और हर चक्र पर नए डेटा के साथ फिर से लिखना ठीक है? या क्या यह केवल नई पंक्तियों को जोड़ने और मौजूदा लोगों को अपडेट करना बेहतर है?

नोट्स:

  1. इस डेटा Orders कि हर रात को डेटाबेस आयात के माध्यम से बना रहेगा उत्पन्न करने के लिए इस्तेमाल किया जाएगा। OrderItems को डेटा फ़ाइल में निर्दिष्ट उत्पाद आईडी से कनेक्ट करने की आवश्यकता होगी, इसलिए हम प्रत्येक आयात के लिए एक ऑटो-वृद्धिशील प्राथमिक कुंजी पर भरोसा नहीं कर सकते हैं; अद्वितीय अल्फान्यूमेरिक आईडी को products से order_items में शामिल होने के लिए उपयोग करने की आवश्यकता होगी।
  2. आदर्श रूप में, मैं विक्रेता डेटा
  3. मैं वेनिला SQL कथन का उपयोग नहीं कर सकते हैं को सामान्य बनाने में आयातक चाहते हैं, इसलिए मुझे लगता है मैं आदेश Product.create(...) और Vendor.create(...) शैली सिंटैक्स का उपयोग करने में एक rake कार्य लिखने के लिए की आवश्यकता होगी।
  4. यह EngineYard

उत्तर

14

मैं उत्पादों को हटाया नहीं जाएगा और हर चक्र पर तालिकाओं विक्रेताओं पर लागू किया जाएगा। क्या यह एक रेल ऐप है? यदि ऐसा है तो कुछ वास्तव में अच्छे ActiveRecord हेल्पर्स हैं जो आपके लिए आसान होंगे।

आप एक उत्पाद सक्रिय रिकॉर्ड मॉडल है, तो आप कर सकते हैं:

p = Product.find_or_initialize_by_identifier(<id you get from file>) 
p.name = <name from file> 
p.size = <size from file> 
etc... 
p.save! 

find_or_initialize आईडी आपके द्वारा निर्दिष्ट डेटाबेस में उत्पाद देखने जाएगा, और अगर यह यह नहीं मिल सकता है, यह एक नया बनाएँ।इस तरह से करने के बारे में वास्तव में आसान बात यह है कि ActiveRecord केवल डेटा में परिवर्तित होने पर डेटाबेस में ही सहेज लेगा, और यह आपके द्वारा तालिका में मौजूद किसी भी टाइमस्टैम्प फ़ील्ड को स्वचालित रूप से अपडेट करेगा (अपडेटेड_एट)। एक और बात, क्योंकि आप पहचानकर्ता (फ़ाइल से आईडी) द्वारा रिकॉर्ड देख रहे होंगे, मैं डेटाबेस में उस फ़ील्ड पर एक इंडेक्स जोड़ना सुनिश्चित करता हूं।

इसे पूरा करने के लिए एक रेक कार्य करने के लिए, मैं आपके रेल ऐप की lib/कार्यों निर्देशिका में एक रेक फ़ाइल जोड़ूंगा। हम इसे डेटा कॉल करेंगे। रेक।

data.rake अंदर

, यह कुछ इस तरह दिखेगा:

namespace :data do 
    desc "import data from files to database" 
    task :import => :environment do 
    file = File.open(<file to import>) 
    file.each do |line| 
     attrs = line.split(":") 
     p = Product.find_or_initialize_by_identifier(attrs[0]) 
     p.name = attrs[1] 
     etc... 
     p.save! 
    end 
    end 
end 

रेक कार्य कॉल करने के लिए से, का उपयोग करें: कमांड लाइन से "रेक डेटा आयात"।

+0

मैं इस कोशिश की, लेकिन मैं मुख्य के लिए त्रुटि 'अपरिभाषित स्थानीय चर या विधि 'डेटा' हो रही है: Object'। कोई विचार क्यों हो रहा है? – Nick

+0

मुद्दा यह था कि 'नेमस्पेस डेटा डू' को 'नेमस्पेस में बदलना था: डेटा करें'। – Nick

0

चूंकि उत्पाद वास्तव में अक्सर नहीं बदलते हैं, इसलिए सबसे अच्छा तरीका यह है कि मैं केवल उन रिकॉर्ड को अपडेट करना चाहता हूं जो बदलते हैं।

  1. एक भी एसक्यूएल बयान का इस्तेमाल सभी डेल्टा
  2. मास अपडेट प्राप्त करें

आप मॉडल में अपने सामान्य कोड हो रही है, आप Product.create और Vendor.create वरना यह इस्तेमाल कर सकते हैं बस एक ओवरकिल होगा। साथ ही, एक एकल SQL लेनदेन में एकाधिक रिकॉर्ड डालने में देखें, यह बहुत तेज़ है।

+0

जैसा कि मेरे प्रश्न में उल्लेख किया गया है, मैं __cannot__ एक वेनिला एसक्यूएल कथन का उपयोग करता हूं। –

0
  • एक आयातक रेक कार्य है कि cronned है
  • तेज़ सीएसवी या के माध्यम से वेनिला रूबी की तरह का उपयोग कर लाइन द्वारा फ़ाइल लाइन पार्स बनाएँ:

file.each करना | लाइन | products_array = line.split (":") अंत

  • स्प्लिट पर प्रत्येक पंक्ति ":" और एक हैश
  • में में धक्का इस तरह के रूप में अपने डाटाबेस को भरने के लिए एक find_or_initialize का उपयोग करें:

    Product.find_or_initialize_by_name_and_vendor_id ("foo" 111)

+0

आप 'find_or_initialize_by_name_and_vendor_id' का उपयोग क्यों कर रहे हैं? क्या यह उत्पाद 'accepts_nested_attributes_for: विक्रेता' का सुझाव देता है? –

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