रेल प्रवास में अशक्त न होने वाले कॉलम को कैसे बदला जाए?


188

मैंने पिछले माइग्रेशन में एक तिथि स्तंभ बनाया था और इसे अशक्त होने के लिए सेट किया था। अब मैं इसे बदलना चाहता हूं कि यह अशक्त न हो। मैं यह कैसे कर सकता हूँ कि उस डेटाबेस में अशक्त पंक्तियाँ हैं? यदि वे वर्तमान में अशक्त हैं, तो मैं उन कॉलमों को Time.now पर सेट करना ठीक हूं।

जवाबों:


204

यदि आप इसे एक प्रवास में करते हैं तो आप शायद इसे इस तरह से कर सकते हैं:

# Make sure no null value exist
MyModel.where(date_column: nil).update_all(date_column: Time.now)

# Change the column to not allow null
change_column :my_models, :date_column, :datetime, null: false

1
सिर्फ एक नोट, क्योंकि इसने मेरे देव डेटाबेस को नष्ट कर दिया। बल्कि स्पष्ट हैश सिंटैक्स का उपयोग करें, जैसे MyModel.update_all({:date_column => Time.now}, {:date_column => nil}):। आपके मूल रूप में क्वेरी ने मेरे सभी मॉडलों को क्षेत्र में शून्य मान दिया है।
dimitarvp

अद्यतन के लिए धन्यवाद। मुझे पता है कि यह ऐसा मामला नहीं था जब मैंने यह उत्तर लिखा था, लेकिन मुझे याद नहीं है कि रूबी या रोआर का कौन सा संस्करण मैं उस समय उपयोग कर रहा था।
डैनमैन

1
क्या आपके पास इस माइग्रेशन में 'अप' / 'डाउन' पद्धति का उपयोग है या आप माइग्रेशन में सरल परिवर्तन विधि का उपयोग कर सकते हैं?
EE33

2
changeविधि इसलिए इस मामले के लिए अनुकूल नहीं है क्योंकि (1) update_allविधि दोनों विस्थापित और एक संभावित वापस लाएं पर निष्पादित होगा। यह सबसे बुरी बात नहीं हो सकती है, लेकिन क्योंकि (2) माइग्रेशन में यह जानने का कोई तरीका नहीं है कि संभावित रिवर्ट से कॉलम को क्या बदला गया। तो इस मामले के लिए मैं के साथ रहना होगा upऔर down
DanneManne

2
रुचि रखने वाले किसी भी व्यक्ति के लिए, मेरा जवाब दिखाता है कि यह एक ही चरण में कैसे किया जाए।
रिक स्मिथ

167

रेल 4 में, यह एक बेहतर (DRYer) समाधान है:

change_column_null :my_models, :date_column, false

यह सुनिश्चित करने के लिए NULLकि उस कॉलम में मूल्यों के साथ कोई रिकॉर्ड मौजूद नहीं है , आप एक चौथे पैरामीटर को पारित कर सकते हैं, जो NULLमानों के साथ रिकॉर्ड के लिए उपयोग करने के लिए डिफ़ॉल्ट मान है:

change_column_null :my_models, :date_column, false, Time.now

4
यह समस्या का कारण बनता है जब तालिका में पहले से ही शून्य मान होते हैं। मेरा उत्तर देखें
रिक स्मिथ

5
3.2 में भी उपलब्ध है। डिफ़ॉल्ट मान सेट करने के लिए 4 डी पैरामीटर भी है जहाँ मान शून्य है।
टॉक्सिक

1
प्लस 1 के लिए change_column_null। हालाँकि रिक स्मिथ की टिप्पणी ऊपर एक बहुत ही मान्य मामला है।
0112

शून्य मानों को अद्यतन करने के लिए क्वेरी जोड़ने के लिए अद्यतन किया गया। 4 वाँ पैरामीटर (डिफ़ॉल्ट मान) केवल तब उपयोगी होता है जब आप वास्तव में भविष्य के रिकॉर्ड के लिए भी डिफ़ॉल्ट होना चाहते हैं।
mrbrdo

3
वास्तव में, रेल्स 4.2 डॉक्स के अनुसार, 4 डी परम भविष्य के रिकॉर्ड के लिए एक डिफ़ॉल्ट मान सेट नहीं करता है: "विधि मौजूदा + NULL + s को किसी अन्य मान से बदलने के लिए एक वैकल्पिक चौथे तर्क को स्वीकार करती है। कृपया ध्यान दें कि चौथा तर्क सेट नहीं होता है। एक कॉलम डिफ़ॉल्ट है। "
माइक फिशर

70

रेल 4 (अन्य रेल 4 उत्तर में समस्याएं हैं):

def change
  change_column_null(:users, :admin, false, <put a default value here> )
  # change_column(:users, :admin, :string, :default => "")
end

NULL के साथ एक कॉलम बदलने से NULL को समस्या नहीं होने दी जाएगी। यह ठीक उसी प्रकार का कोड है जो आपके विकास सेटअप में ठीक काम करेगा और तब क्रैश होगा जब आप इसे अपने LIVE उत्पादन में तैनात करने का प्रयास करेंगे । आपको पहले NULL मान को किसी मान्य चीज़ में बदलना चाहिए और फिर NULL को अस्वीकृत करना चाहिए। 4 वाँ मूल्य change_column_nullवास्तव में ऐसा ही करता है। अधिक विवरण के लिए प्रलेखन देखें ।

इसके अलावा, मैं आम तौर पर क्षेत्र के लिए एक डिफ़ॉल्ट मान सेट करना पसंद करता हूं इसलिए मुझे हर बार एक नई वस्तु बनाने के लिए क्षेत्र के मूल्य को निर्दिष्ट करने की आवश्यकता नहीं होगी। मैंने टिप्पणी कोड को भी शामिल किया।


3
रेल 4 के लिए, यह सबसे सटीक और पूर्ण उत्तर प्रतीत होता है, जिसमें कमेंट-आउट डिफ़ॉल्ट सेटिंग भी शामिल है।
माइक फिशर

4
आप एक तालिका में एक नया स्तंभ जोड़ रहे हैं कर रहे हैं और अशक्त के लिए नए मूल्यों सम्मिलित करना चाहते हैं, लेकिन स्तंभ के लिए कोई डिफ़ॉल्ट मान जोड़ने के लिए नहीं करना चाहते हैं, तो आप अपने प्रवास में यह कर सकते हैं: add_column :users, :admin, :stringतोchange_column_null(:admin, :string, false, "new_value_for_existing_records")
colsen

34

एक माइग्रेशन बनाएं change_columnजिसमें एक :default =>मान है।

change_column :my_table, :my_column, :integer, :default => 0, :null => false

देखें: change_column

डेटाबेस इंजन के आधार पर आपको उपयोग करने की आवश्यकता हो सकती है change_column_null


1
इसने मेरे लिए काम किया। स्थानीय रूप से MySql का उपयोग करना। जब हेरोकू (पोस्टग्रेज) में ऐप को धकेला और चलाया गया तो यह उस कॉलम पर तरस गया, जो तब अशक्त नहीं था जब मैं इसे एक अशक्त लिख रहा था - ठीक है। केवल "change_column_null" काम नहीं कर सकता "Change_column ...: null => false" का उपयोग Myqql पर नहीं कर सकता। धन्यवाद।
rtfminc

1
इसलिए परिवर्तन के बाद आपका प्रवासन क्या था_बेल_न्यूअल
js111

1
पोस्ट्स अधिक सख्त है कि MySQL - मुझे उम्मीद है कि इसकी आवश्यकता होगी change_column_null
जेसेकुर्री

3
@rtfminc मैं दृढ़ता से विकास और उत्पादन में एक ही डेटाबेस इंजन का उपयोग करने की सलाह देता हूं, क्योंकि जब यह किनारे के मामलों में आता है तो बहुत सारी समस्याओं से बचा जाता है।
यगुरु


3

में रेल 4.02+ के अनुसार डॉक्स वहाँ की तरह कोई विधि नहीं है update_all2 तर्क के साथ। इसके बजाय कोई इस कोड का उपयोग कर सकता है:

# Make sure no null value exist
MyModel.where(date_column: nil).update_all(date_column: Time.now)

# Change the column to not allow null
change_column :my_models, :date_column, :datetime, null: false

2

यदि आप मौजूदा रिकॉर्ड रखते हैं, तो आप add_timestamps और null का उपयोग नहीं कर सकते हैं, इसलिए यहां समाधान है:

def change
  add_timestamps(:buttons, null: true)

  Button.find_each { |b| b.update(created_at: Time.zone.now, updated_at: Time.zone.now) }

  change_column_null(:buttons, :created_at, false)
  change_column_null(:buttons, :updated_at, false)
end
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.