किसी मौजूदा तालिका में टाइमस्टैम्प जोड़ें


173

मुझे मौजूदा तालिका में टाइमस्टैम्प ( created_atऔर updated_at) जोड़ने की आवश्यकता है । मैंने निम्न कोड की कोशिश की, लेकिन यह काम नहीं किया।

class AddTimestampsToUser < ActiveRecord::Migration
    def change_table
        add_timestamps(:users)
    end
end

जवाबों:


211

टाइमस्टैम्प सहायक केवल create_tableब्लॉक में उपलब्ध है । आप स्तंभ प्रकारों को मैन्युअल रूप से निर्दिष्ट करके इन स्तंभों को जोड़ सकते हैं:

class AddTimestampsToUser < ActiveRecord::Migration
  def change_table
    add_column :users, :created_at, :datetime, null: false
    add_column :users, :updated_at, :datetime, null: false
  end
end

हालाँकि, यह add_timestampsआपके द्वारा निर्दिष्ट विधि के समान ट्रेस सिंटैक्स नहीं है , फिर भी रेल इन कॉलमों को टाइमस्टैम्प कॉलम के रूप में मानेंगे, और सामान्य रूप से मानों को अपडेट करेंगे।


10
यह मेरे लिए रेल 4 में काम नहीं किया। "म्यू बहुत छोटा है" द्वारा नीचे दिया गया समाधान काम कर रहा है।
newUserNameHere

21
rails g migration AddTimestampsToUser created_at:datetime updated_at:datetime- ऊपर दिए गए माइग्रेशन को उत्पन्न करने के लिए एक शॉर्टकट।
कॉन्स्टेंटाइन कल्बज़ोव

2
इस माइग्रेशन को चलाने में त्रुटि होती है PG::NotNullViolation: ERROR: column "created_at" contains null value क्योंकि मेरी तालिका में पहले से ही डेटा शामिल है जो अशक्त नहीं का उल्लंघन करता है। ऐसा करने का कोई भी बेहतर तरीका नहीं है कि पहले कम से कम अशक्त गर्भनिरोधक को हटा दिया जाए और बाद में इसे जोड़ा जाए?
एम। हबीब

1
@ एम। हबीब मुझे ऐसा नहीं लगता, लेकिन यह जवाब सभी को एक प्रवास में अच्छी तरह से समझाया जाता है।
छोटा

1
@ एम। हबीब इस बात पर निर्भर करता है कि आपको क्या लगता है कि डिफ़ॉल्ट मूल्य के लिए सबसे अधिक समझ में आता है, आप कर सकते हैं add_column :users, :updated_at, :datetime, null: false, default: Time.zone.nowTime.zone.nowकेवल एक उदाहरण है, आपको अपने तर्क के लिए जो भी मूल्य समझ में आता है उसका उपयोग करना चाहिए।
डेलॉन्ग गाओ

91

माइग्रेशन केवल दो वर्ग विधियाँ हैं (या 3.1 में आवृत्ति विधि): upऔर down(और कभी-कभी change3.1 में एक आवृत्ति विधि)। आप upविधि में जाने के लिए अपने बदलाव चाहते हैं :

class AddTimestampsToUser < ActiveRecord::Migration
  def self.up # Or `def up` in 3.1
    change_table :users do |t|
      t.timestamps
    end
  end
  def self.down # Or `def down` in 3.1
    remove_column :users, :created_at
    remove_column :users, :updated_at
  end
end

यदि आप 3.1 में हैं तो आप भी इस्तेमाल कर सकते हैं change(धन्यवाद डेव):

class AddTimestampsToUser < ActiveRecord::Migration
  def change
    change_table(:users) { |t| t.timestamps }
  end
end

शायद आप भ्रमित कर रहे हैं def change, def change_tableऔर change_table

देखें माइग्रेशन मार्गदर्शिका अधिक जानकारी के लिए।


1
(ठीक है, changeअब विधि है, हालांकि इस मामले में, मुद्दा नहीं :)
डेव न्यूटन 1

@Dave: काफी सच है, मैं संस्करण के मुद्दों से बचने के लिए जेनेरिक के लिए गया था, लेकिन changeएक उल्लेख के लायक है इसलिए मैं इसे भी जोड़ दूंगा।
म्यू बहुत छोटा है

यह सच है लेकिन मैंने सुना है कि वास्तव में 3.1 के साथ बदल रहा है और 'डाउन' वास्तव में दूर जा रहा है। स्वचालित रूप से डाउन विधि का पता लगाने के लिए रेल। क्या आपने उसके बारे में सुना है?
माइकल ड्यूरेंट

@ मिचेल: मैं 3.1 ऐप के साथ विशेष रूप से MongoDB का उपयोग कर रहा हूं, इसलिए मैं 3.1 एआर माइग्रेशन के साथ काम नहीं कर रहा हूं। डॉक्स इंगित करता है कि सब कुछ उदाहरण के तरीकों (अज्ञात कारणों से) की ओर बढ़ रहा है।
म्यू बहुत कम है

@MichaelDurrant, कई परिदृश्य हैं जो "परिवर्तन" अभी कवर नहीं करते हैं, अगर ऊपर / नीचे चले जाते हैं तो कुछ नाराज लोग होंगे :) (माइग्रेशन टकराव से बचने के लिए अपने परिवर्तन प्रवास में "एक" जब तक "खंड जोड़ें" और प्रयास करें उस बैक को रोल करना ...) यह टिप्पणी करने के 3 साल बाद भी, मुझे नहीं लगता कि यह बदल रहा है। :)
फैंड्रायड

76

आपका मूल कोड दाईं ओर बहुत करीब है, आपको बस एक अलग विधि नाम का उपयोग करने की आवश्यकता है। यदि आप 3.1 या बाद के रेल का उपयोग कर रहे हैं, तो आपको changeइसके बजाय एक विधि को परिभाषित करने की आवश्यकता है change_table:

class AddTimestampsToUser < ActiveRecord::Migration
  def change
    add_timestamps(:users)
  end
end

यदि आप एक पुराने संस्करण का उपयोग कर रहे हैं, तो आपको इसके बजाय परिभाषित upऔर downविधियों की आवश्यकता होगी change_table:

class AddTimestampsToUser < ActiveRecord::Migration
  def up
    add_timestamps(:users)
  end

  def down
    remove_timestamps(:users)
  end
end

59

@ user1899434 की प्रतिक्रिया इस तथ्य पर उठाई गई कि यहां "मौजूदा" तालिका का मतलब हो सकता है कि इसमें पहले से रिकॉर्ड वाली एक तालिका है, रिकॉर्ड जो आप छोड़ना नहीं चाहते हैं। इसलिए जब आप शून्य के साथ टाइमस्टैम्प जोड़ते हैं: गलत, जो कि डिफ़ॉल्ट है और अक्सर वांछनीय है, जो मौजूदा रिकॉर्ड सभी अमान्य हैं।

लेकिन मुझे लगता है कि उत्तर को एक माइग्रेशन में दो चरणों के संयोजन से और साथ ही अधिक अर्थपूर्ण add_timestamps विधि का उपयोग करके सुधार किया जा सकता है:

def change
  add_timestamps :projects, default: Time.zone.now
  change_column_default :projects, :created_at, nil
  change_column_default :projects, :updated_at, nil
end

आप कुछ अन्य टाइमस्टैम्प को स्थानापन्न कर सकते हैं DateTime.now, जैसे यदि आप चाहते थे कि preexisting रिकॉर्ड समय के बजाय समय पर बनाए / अपडेट किए जाएं।


2
गजब का। धन्यवाद! बस एक नोट - Time.zone.nowअगर हमें अपना कोड सही समय क्षेत्र का पालन करना है तो क्या उपयोग किया जाना चाहिए।
जॉन गैलाघर

4
डिफ़ॉल्ट को सेट करने में एक समस्या Time.zone.nowहै जो यह है कि यह माइग्रेशन चलाने के समय बनाई गई समय आवृत्ति लौटाएगा और डिफ़ॉल्ट के रूप में उस समय का उपयोग करेगा। नई वस्तुओं को एक नया समय नहीं मिलेगा।
तोवी न्यूमैन

38
class AddTimestampsToUser < ActiveRecord::Migration
  def change
    change_table :users do |t|
      t.timestamps
    end
  end
end

उपलब्ध परिवर्तन हैं

change_table :table do |t|
  t.column
  t.index
  t.timestamps
  t.change
  t.change_default
  t.rename
  t.references
  t.belongs_to
  t.string
  t.text
  t.integer
  t.float
  t.decimal
  t.datetime
  t.timestamp
  t.time
  t.date
  t.binary
  t.boolean
  t.remove
  t.remove_references
  t.remove_belongs_to
  t.remove_index
  t.remove_timestamps
end

http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html


10

निक डेविस का जवाब मौजूदा डेटा वाली तालिका में टाइमस्टैम्प कॉलम को जोड़ने के मामले में सबसे पूर्ण है। इसका केवल नकारात्मक पक्ष यह है कि यह ActiveRecord::IrreversibleMigrationएक पर उठाएगा db:rollback

इसे दोनों दिशाओं में काम करने के लिए संशोधित किया जाना चाहिए:

def change
  add_timestamps :campaigns, default: DateTime.now
  change_column_default :campaigns, :created_at, from: DateTime.now, to: nil
  change_column_default :campaigns, :updated_at, from: DateTime.now, to: nil
end

यह मेरे लिए ठीक वैसा ही काम नहीं हुआ जैसा कि रेल्स 4.2.7 पर लिखा गया था (मुझे लगता change_column_defaultहै कि वह समर्थन नहीं करता है fromऔर toउस संस्करण में?), लेकिन मैंने इस विचार को लिया और up/downएक ही changeविधि के बजाय तरीकों का निर्माण किया और यह एक आकर्षण की तरह काम किया!
गर


4

निश्चित रूप से नहीं जब यह पेश किया गया था, लेकिन रेल 5.2.1 में आप यह कर सकते हैं:

class AddTimestampsToMyTable < ActiveRecord::Migration[5.2]
  def change
    add_timestamps :my_table
  end
end

सक्रिय रिकॉर्ड माइग्रेशन डॉक्स में " परिवर्तन विधि का उपयोग " अधिक देखने के लिए ।


मैंने इसे माइग्रेशन [5.1] के साथ काम नहीं किया; फिर मैंने नंबर बदलकर [5.2] कर दिया है और रेल्स ने मुझे बताया कि मैं केवल 5.1, 5.0 या 4.2 का उपयोग कर सकता हूं। मैंने बिना किसी सफलता के साथ 5.0 के साथ प्रयास किया है, फिर सफलता के साथ 4.2 में।
क्या मा

पुराना, मुझे पता है, लेकिन अगर आपके पास मौजूदा रिकॉर्ड्स हैं: के , null: trueबाद:my_table
jomar

2

मैं एक साधारण समारोह है कि आप को जोड़ने के लिए कॉल कर सकते हैं बनाया प्रत्येक मेज (यह मानते हुए कि आप एक मौजूदा डेटाबेस है) created_at और updated_at क्षेत्रों:

  # add created_at and updated_at to each table found.
  def add_datetime
    tables = ActiveRecord::Base.connection.tables
    tables.each do |t|
      ActiveRecord::Base.connection.add_timestamps t  
    end    
  end

2

add_timestamps (table_name, विकल्प = {}) सार्वजनिक

टाइमस्टैम्प (create_at और updated_at) कॉलम को table_name में जोड़ता है। अतिरिक्त विकल्प (जैसे शून्य: असत्य) को #add_column पर अग्रेषित किया जाता है।

class AddTimestampsToUsers < ActiveRecord::Migration
  def change
    add_timestamps(:users, null: false)
  end
end

1

यदि मेरी तालिका में पहले से ही प्रविष्टियाँ हैं, तो उत्तर देने से पहले उत्तर सही प्रतीत होते हैं।

मुझे 'ERROR: कॉलम created_atमें nullमान शामिल हैं'।

ठीक करने के लिए, मैंने इस्तेमाल किया:

def up
  add_column :projects, :created_at, :datetime, default: nil, null: false
  add_column :projects, :updated_at, :datetime, default: nil, null: false
end

मैंने तब माइग्रेशन पर वर्तमान प्रोजेक्ट्स के लिए समय जोड़ने के लिए मणि माइग्रेशन_डेटा का उपयोग किया :

def data
  Project.update_all created_at: Time.now
end

फिर इस माइग्रेशन के बाद बनाई गई सभी परियोजनाएं सही ढंग से अपडेट की जाएंगी। सुनिश्चित करें कि सर्वर को भी पुनरारंभ किया गया है ताकि रेलActiveRecord रिकॉर्ड पर टाइमस्टैम्प को ट्रैक करना शुरू कर दें।


1

यहाँ बहुत सारे उत्तर, लेकिन मैं अपना भी पोस्ट करूँगा क्योंकि पिछले किसी ने भी वास्तव में मेरे लिए काम नहीं किया :)

जैसा कि कुछ ने उल्लेख किया है, #add_timestampsदुर्भाग्य से null: falseप्रतिबंध जोड़ता है , जिससे पुरानी पंक्तियां अमान्य हो जाएंगी क्योंकि उनके पास ये मूल्य आबादी नहीं हैं। यहां अधिकांश उत्तर बताते हैं कि हमने कुछ डिफ़ॉल्ट मान सेट किए हैं (Time.zone.now ) , लेकिन मैं ऐसा नहीं करना चाहूंगा क्योंकि पुराने डेटा के लिए ये डिफ़ॉल्ट टाइमस्टैम्प सही नहीं होंगे। मुझे तालिका में गलत डेटा जोड़ने का मूल्य नहीं दिखता है।

इसलिए मेरा प्रवास सरल था:

class AddTimestampsToUser < ActiveRecord::Migration
  def change_table
    add_column :projects, :created_at, :datetime
    add_column :projects, :updated_at, :datetime
  end
end

नहीं null: false, कोई अन्य प्रतिबंध नहीं। पुरानी पंक्तियों के साथ मान्य किया जा रहा है के लिए जारी रहेगा created_atके रूप में NULL, और update_atके रूप में NULL(जब तक कुछ अद्यतन पंक्ति में किया जाता है)। नई पंक्तियों होगा created_atऔर updated_atअपेक्षा के अनुरूप आबादी।


1

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

class AddTimestampsToUsers < ActiveRecord::Migration def change add_timestamps :users, default: -> { 'now()' }, null: false end end


1

उपयोग करना Time.currentएक अच्छी शैली है https://github.com/rubocop-hq/rails-style-guide#timenow

def change
  change_table :users do |t|
    t.timestamps default: Time.current
    t.change_default :created_at, from: Time.current, to: nil
    t.change_default :updated_at, from: Time.current, to: nil
  end
end

या

def change
  add_timestamps :users, default: Time.current
  change_column_default :users, :created_at, from: Time.current, to: nil
  change_column_default :users, :updated_at, from: Time.current, to: nil
end

1

मौजूदा तालिका में टाइमस्टैम्प को जोड़ने के लिए यह एक सरल है।

class AddTimeStampToCustomFieldMeatadata < ActiveRecord::Migration
  def change
    add_timestamps :custom_field_metadata
  end
end

0

उन लोगों के लिए जो रेल का उपयोग नहीं करते हैं, लेकिन एक्टिवरकार्ड का उपयोग करते हैं, निम्नलिखित एक मौजूदा मॉडल में एक कॉलम भी जोड़ता है, उदाहरण एक पूर्णांक फ़ील्ड के लिए है।

ActiveRecord::Schema.define do
  change_table 'MYTABLE' do |table|
    add_column(:mytable, :my_field_name, :integer)
  end
end

0

यह रेल 4.2 के लिए changeनहीं है change_table:

class AddTimestampsToUsers < ActiveRecord::Migration
  def change
    add_timestamps(:users)
  end
end

0

यह रेल 5.0.7 में एक स्वच्छ समाधान की तरह लगता है (change_column_null विधि की खोज की):

def change
  add_timestamps :candidate_offices, default: nil, null: true
  change_column_null(:candidate_offices, :created_at, false, Time.zone.now)
  change_column_null(:candidate_offices, :created_at, false, Time.zone.now)
end

0

मैं 5.0 रेल पर हूं और इनमें से किसी भी विकल्प पर काम नहीं किया गया।

केवल एक चीज जो काम करती थी वह होने के प्रकार का उपयोग कर रही थी: टाइमस्टैम्प और नहीं: डेटाइम

def change
    add_column :users, :created_at, :timestamp
    add_column :users, :updated_at, :timestamp
end

-1

मैंने व्यक्तिगत रूप से निम्नलिखित का उपयोग किया है, और इसने वर्तमान समय / तिथि के साथ पिछले सभी रिकॉर्डों को अद्यतन किया है:

add_column :<table>, :created_at, :datetime, default: Time.zone.now, null: false
add_column :<table>, :updated_at, :datetime, default: Time.zone.now, null: false

-2

मैं रेल 5 पर एक ही मुद्दे में भाग गया उपयोग करने की कोशिश कर रहा

change_table :my_table do |t|
    t.timestamps
end

मैं निम्नलिखित के साथ मैन्युअल रूप से टाइमस्टैम्प कॉलम जोड़ने में सक्षम था:

change_table :my_table do |t|
    t.datetime :created_at, null: false, default: DateTime.now
    t.datetime :updated_at, null: false, default: DateTime.now
end

क्या यह हमेशा उस समय के साथ डिफ़ॉल्ट मान सेट नहीं होगा जिस समय माइग्रेशन चलाया गया था? (इसलिए वास्तव में एक गतिशील टाइमस्टैम्प डीबी द्वारा संभाला नहीं गया है)
गिलियूम पेटिट

आपके db में पहले से मौजूद रिकॉर्ड्स के लिए, हाँ, यह create_at को सेट करेगा और अद्यतन_at को माइग्रेटटाइम में स्थानांतरित करेगा। हालांकि, पहले से उन मूल्यों के बिना, आइडल कैसे आप उन मूल्यों को इनिशियलाइज़ करेंगे। संपादित करें: यह सिर्फ उस पंक्ति के इतिहास की शुरुआत माना जाएगा
एंड्रेस रोजलेस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.