2010-08-13 23 views
22

रेक डीबी: बीज आपके डीबी को एक ऐप के लिए डिफ़ॉल्ट डेटाबेस मानों के साथ पॉप्युलेट करता है? तो क्या होगा यदि आपके पास पहले से ही बीज है और आपको इसमें जोड़ने की ज़रूरत है (आप एक नई सुविधा जोड़ते हैं जिसके लिए बीज की आवश्यकता होती है)। मेरे अनुभव में, जब मैं रेक डीबी चला गया: बीज फिर से, यह मौजूदा सामग्री को पहले से जोड़ दिया गया है इसलिए मौजूदा सामग्री डबल हो गई है।रेक डीबी में संलग्न: रेल में बीज और डेटा डुप्लिकेट किए बिना इसे चला रहा है

मुझे कुछ बीज जोड़ने और जब दौड़ने की ज़रूरत है, तो इसे केवल नवीनतम जोड़ना चाहिए, और मौजूदा बीजों को अनदेखा करना चाहिए। मैं इसके साथ कैसे जा सकता हूं? (गंदा, नोब रास्ता मैं आमतौर पर अपने पूरे डीबी को तोड़ने के लिए फिर से बीज चलाता हूं, लेकिन उत्पादन में ऐसा करने में बहुत चालाक नहीं है, है ना?)

उत्तर

10

मैं ऐसा कुछ करता हूं .... जब मुझे आवश्यकता होती है seeds.rb में एक उपयोगकर्ता

जोड़ने के लिए:

if User.count == 0 
    puts "Creating admin user" 
    User.create(:role=>:admin, :username=>'blagh', :etc=>:etc) 
end 

आपको लगता है कि अधिक से अधिक दिलचस्प हो सकता है, लेकिन इस मामले में, आप इसे फिर से जरूरत के मुताबिक चला सकते हैं।

User.find_or_create_by_username_and_role(
    :username => "admin", 
    :role => "admin", 
    :email => "[email protected]") 

यहाँ संभावित परिणाम होते हैं: इस प्रकार

+0

हममम तो मैं मूल रूप से सिर्फ एक गिनती == 0 टेबल मैं अपने बीज में आबादी की जरूरत है सुनिश्चित करने के लिए वे सही नकल नहीं होगा में से किसी को जोड़ सकते हैं? धन्यवाद! मैं केवल – corroded

+4

के लिए एक रेक कार्य करने की सोच रहा था, आपको उन्हें बनाने से पहले विशिष्ट रिकॉर्ड भी ढूंढना पड़ सकता है। उनकी उपस्थिति की जांच करें: उदा। 'User.create (: name =>" बॉब ") जब तक user.find_by_name (" बॉब ")' –

36

यह करने के लिए एक क्लीनर तरीका, find_or_create_by का उपयोग करना है

  1. एक रिकॉर्ड उपयोगकर्ता नाम "व्यवस्थापक" और भूमिका "व्यवस्थापक" के साथ मौजूद है । यह रिकॉर्ड नए ई-मेल के साथ अपडेट नहीं किया जाएगा यदि यह पहले से मौजूद है, लेकिन इसे दोगुना नहीं किया जाएगा।
  2. उपयोगकर्ता नाम "व्यवस्थापक" और भूमिका "व्यवस्थापक" के साथ एक रिकॉर्ड मौजूद नहीं है। उपरोक्त रिकॉर्ड बनाया जाएगा।
  3. ध्यान दें कि यदि उपयोगकर्ता नाम/भूमिका मानदंडों में से केवल एक ही संतुष्ट है, तो यह उपर्युक्त रिकॉर्ड बनाएगा। यह सुनिश्चित करने के लिए सही मानदंडों का उपयोग करें कि आप अद्वितीय कुछ नहीं रहना चाहते हैं।
+1

1. गलत है। कोई भी संपत्ति अद्यतन नहीं की जाएगी। यदि आप रिकॉर्ड अपडेट करना चाहते हैं तो आपको बाद में अपडेट करना होगा। जैसा कि नाम इंगित करता है कि यह मिल जाएगा या बनायेगा, नहीं ढूंढ पाएगा या अपडेट नहीं करेगा। –

+1

@ बिललीपर - आप बिल्कुल सही हैं। मेरी धारणा को सही करने के लिए धन्यवाद - मैंने अभी जवाब अपडेट किया है। – sscirrus

+0

कोई समस्या नहीं, यह पता चला कि एक कठिन तरीका भी है क्योंकि मुझे यकीन है कि बहुत से लोग हैं। निश्चित नहीं है कि कोई मानक find_create_or_update क्यों नहीं है, लेकिन विभिन्न दृष्टिकोणों के साथ वहां कई उदाहरण हैं। –

-4

बस User.delete_all और अपने मॉडल में शामिल सभी मॉडलों के लिए जो आपके बीज.आरबी फ़ाइल की शुरुआत में शामिल हैं। निश्चित रूप से कोई डुप्लिकेट मान नहीं होगा।

+2

आप प्रश्न की गलत व्याख्या कर रहे हैं। ओपी स्पष्ट रूप से उल्लेख करता है कि वह इसे उत्पादन में करना चाहता है और डीबी को कम करना जोखिम भरा है। आप जवाब का हिस्सा अनदेखा कर रहे हैं। मैं आपको इसे हटाने की सलाह दूंगा। –

+0

इसमें दोनों प्रदर्शन समस्याएं और डेटा जोखिम हैं - यदि किसी भी बीज डेटा को कभी अपडेट किया गया था या यदि यह किसी भी अन्य माइग्रेशन द्वारा कभी प्रभावित हुआ था, तो सबकुछ हटाने और रीसेट करने का प्रयास करने से आपके इच्छित डेटा को आवश्यक रूप से पुनर्स्थापित नहीं किया जाएगा। – sscirrus

0


departments = ["this", "that"] 
departments.each{|d| Department.where(:name => d).first_or_create} 

से

departments = ["this", "that", "there", "then"] 
departments.each{|d| Department.where(:name => d).first_or_create} 
को जोड़ना

इस एक सरल उदाहरण है,


अद्यतन कर रहा है/नाम बदलने


departments = ["this", "that", "there", "then"] 
departments.each{|d| Department.where(:name => d).first_or_create} 

से

को
departments = ["these", "those", "there", "then"] 
new_names = [['these', 'this'],['those','that']] 

new_names.each do |new| 
    Department.where(:name => new).group_by(&:name).each do |name, depts| 
    depts.first.update_column :name, new[0] if new[1] == name # skips validation 
    # depts[1..-1].each(&:destroy) if depts.size > 1 # paranoid mode 
    end 
end 

departments.each{|d| Department.where(:name => d).first_or_create} 

महत्वपूर्ण: आपको departments सरणी के तत्वों को अद्यतन करने की आवश्यकता है अन्यथा डुप्लिकेशंस निश्चित रूप से होगा।

काम के आसपास: एक validates_uniqueness_of सत्यापन या विशिष्टता सभी आवश्यक विशेषताओं की तुलना में एक सत्यापन जोड़े लेकिन methods skipping validations प्रयोग नहीं करते।

1

इस तरह की चीज़ के लिए मेरी प्राथमिकता बीज.आरबी फ़ाइल का उपयोग करने के बजाय कस्टम रेक कार्य बनाना है।

यदि आप उपयोगकर्ताओं को थोक बनाने की कोशिश कर रहे हैं तो मैं डेटा के साथ एक .csv फाइलें बनाउंगा, फिर import_users नामक एक रेक कार्य बनाएं और इसे फ़ाइल नाम दें। फिर उपयोगकर्ता रिकॉर्ड बनाने के लिए इसके माध्यम से लूप करें।

lib में/कार्य/import_users.rake:

namespace :my_app do 
    desc "Import Users from a .csv" 
    task :import_users => :environment do 
    # loop through records and create users 
    end 
end 

फिर तो जैसे चलाएँ: rake bundle exec my_app:import_users path/to/.csv

आप उत्पादन में इसे चलाने के लिए की जरूरत है: RAILS_ENV=production bundle exec rake my_app:import_users /path/to/.csv

7

एक अन्य विकल्प हो सकता है मामूली प्रदर्शन लाभ:

# This example assumes that a role consists of just an id and a title. 

roles = ['Admin', 'User', 'Other'] 
existing_roles = Role.all.map { |r| r.title } 

roles.each do |role| 
    unless existing_roles.include?(role) 
    Role.create!(title: role) 
    end 
end 

मैं वें स्याही जो इस तरह से कर रही है, आपको केवल एक डीबी कॉल करना है जो कि मौजूद है, फिर आपको केवल फिर से कॉल करने की आवश्यकता है यदि कुछ नहीं है और इसे बनाने की आवश्यकता है।

+4

मौजूदा_रोल्स = Role.all.map {| r | r.title} को Role.all.collect (&: title) के रूप में लिखा जा सकता है, या रेल 3.2 में बस Role.pluck (शीर्षक) – mkk

+1

अच्छा बिंदु, धन्यवाद mkk। – Lexun

+1

भी '(भूमिकाएं - मौजूदा_रोल्स) कर सकते हैं। प्रत्येक {| भूमिका | Role.create! शीर्षक: भूमिका} ' –

0

एक वास्तव में hackable तरह से मौजूदा डेटा बाहर टिप्पणी करने के लिए हो सकता है, कि कैसे मैं यह किया है, और यह मेरे लिए ठीक काम किया

=begin 

#Commented Out these lines since they where already seeded 
    PayType.create!(:name => "Net Banking") 
    PayType.create!(:name => "Coupouns Pay") 

=end 
#New data to be used by seeds 

PayType.create!(:name => "Check") 
PayType.create!(:name => "Credit card") 
PayType.create!(:name => "Purchase order") 
PayType.create!(:name => "Cash on delivery") 

ऐसा करने के बाद सिर्फ टिप्पणियों को निकाल

-1

एक और तुच्छ विकल्प:

#categories => name, color 
categories = [ 
    [ "Category 1", "#e51c23" ], 
    [ "Category 2", "#673ab7" ] 
] 

categories.each do |name, color| 
    if (Category.where(:name => name).present? == false) 
    Category.create(name: name, color: color) 
    end 
end 

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

  • कोई संबंधित समस्या नहीं^_^