Varolan bir tabloya zaman damgaları ekleme


173

Varolan bir tabloya zaman damgaları ( created_at& updated_at) eklemeniz gerekir . Aşağıdaki kodu denedim ama işe yaramadı.

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

Yanıtlar:


211

Zaman damgası yardımcısı yalnızca create_tableblokta kullanılabilir. Sütun türlerini manuel olarak belirterek bu sütunları ekleyebilirsiniz:

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

Bu, add_timestampsyukarıda belirttiğiniz yöntemle aynı kısa sözdizimine sahip olmasa da , Rails yine de bu sütunlara zaman damgası sütunları olarak davranır ve değerleri normal olarak güncelleştirir.


10
Bu Rails 4 benim için işe yaramadı. "Mu çok kısa" tarafından aşağıdaki çözüm çalışıyor.
— newUserNameHere

21
rails g migration AddTimestampsToUser created_at:datetime updated_at:datetime- yukarıdaki taşımayı oluşturmak için bir kısayol.
— Konstantine Kalbazov

2
PG::NotNullViolation: ERROR: column "created_at" contains null value Tablonuz zaten boş kısıtlamayı ihlal eden veriler içerdiğinden, bu geçişin çalıştırılması hataya neden oluyor . Bunu yapmanın daha iyi bir yolu, önce boş olmayan kontratı kaldırmak ve sonra eklemek.
— M. Habib

1
@ M.Habib Ben öyle düşünmüyorum, ama bu cevap hepsini tek bir göçte güzelce içeriyor .
— littleforest

1
@ M.Habib, yapabileceğiniz varsayılan değer için en anlamlı olanın ne olduğuna bağlıdır add_column :users, :updated_at, :datetime, null: false, default: Time.zone.now. Time.zone.nowsadece bir örnek, mantığınız için anlamlı olan her değeri kullanmalısınız.
— Delong Gao

91

Taşıma işlemleri yalnızca iki sınıf yöntemidir (veya 3.1'deki örnek yöntemler): upve down(ve bazen change3.1'deki bir örnek yöntemidir). Değişikliklerinizin upyönteme geçmesini istiyorsunuz :

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 yılında iseniz o zaman da kullanabilirsiniz change(teşekkürler Dave):

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

Belki karıştırıyorsun def change, def change_tableve change_table.

Daha fazla ayrıntı için taşıma kılavuzuna bakın.


1
(Peki, changeşimdi yöntem var, ancak bu durumda, sorun değil :)
— Dave Newton

@Dave: Yeterince doğru, sürüm sorunlarından kaçınmak için genel için gittim ama changebahsetmeye değer, bu yüzden ben de ekleyeceğim.
— mu çok kısa

Doğru mu ama bunun 3.1 ile gerçekten değiştiğini duydum ve 'aşağı' gerçekten gidiyor. Aşağı yöntemi otomatik olarak bulmak için raylar. Bunu duydun mu?
— Michael Durrant

@Michael: MongoDB'yi sadece üzerinde çalıştığım 3.1 uygulamasıyla kullanıyorum, bu yüzden 3.1 AR geçişi ile çalışmadım. Dokümanlar, her şeyin örnek yöntemlere doğru ilerlediğini gösterir (bilinmeyen nedenlerle).
— mu çok kısa

@MichaelDurrant, şu anda "değişim" in kapsamadığı pek çok senaryo var, eğer yukarı / aşağı giderseniz bazı kızgın insanlar olacak :) Bu geri dönüşü ...) Bu yorumu yaptıktan 3 yıl sonra bile, bunun değiştiğini sanmıyorum. :)
— frandroid

76

Orijinal kodunuz sağa çok yakın, sadece farklı bir yöntem adı kullanmanız gerekiyor. Rails 3.1 veya üstünü kullanıyorsanız, aşağıdakiler changeyerine bir yöntem tanımlamanız gerekir change_table:

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

Eski bir sürüm kullanıyorsanız aşağıdakileri tanımlamanız upve downyöntemleriniz gerekir change_table:

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

  def down
    remove_timestamps(:users)
  end
end

59

@ user1899434'ün yanıtı, buradaki "mevcut" bir tablonun, içinde zaten kayıtların bulunduğu bir tablo, bırakmak istemeyebileceğiniz kayıtlar olabileceği gerçeğini aldı. Bu nedenle, varsayılan ve genellikle istenen null: false ile zaman damgaları eklediğinizde, varolan bu kayıtların tümü geçersizdir.

Ancak, iki adımı bir geçişte birleştirerek ve daha semantik add_timestamps yöntemini kullanarak bu cevabın geliştirilebileceğini düşünüyorum:

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Önceden varolan kayıtların zamanın başlangıcında oluşturulmasını / güncellenmesini istiyorsanız, bunun yerine başka bir zaman damgasını kullanabilirsiniz.


2
İnanılmaz. Teşekkür ederim! Sadece bir not - Time.zone.nowkodumuzun doğru saat dilimine uymasını istiyorsak ne kullanmamız gerektiğidir.
— John Gallagher

4
Varsayılanın ayarlanmasında bir sorun vardır Time.zone.now; bunun nedeni, taşıma çalıştırıldığında oluşturulan Time örneğini döndürmesi ve bu zamanı varsayılan olarak kullanmasıdır. Yeni nesneler yeni bir Zaman örneği almaz.
— Tovi Newman

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

Mevcut dönüşümler

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

Nick Davies yanıtı , mevcut verileri içeren bir tabloya zaman damgası sütunları ekleme açısından en eksiksiz yanıttır . Tek dezavantajı, ActiveRecord::IrreversibleMigrationa db:rollback.

Her iki yönde de çalışacak şekilde değiştirilmelidir:

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

Bu tam olarak benim için Rails 4.2.7 (sanmıyorum ve bu sürümde change_column_defaultdesteklemiyor mu?) Yazdığı gibi çalışmadı , ama bu fikri aldım ve tek bir yöntem yerine yöntemler oluşturdum ve bir cazibe gibi çalıştı! fromtoup/downchange
— gar


4

tam olarak ne zaman tanıtıldığından emin değilim, ancak raylar 5.2.1'de bunu yapabilirsiniz:

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

daha fazla bilgi için etkin kayıt taşıma belgelerindeki " değişiklik yöntemini kullanma " konusuna bakın .


Göç ile çalışmasını sağlayamadım [5.1]; daha sonra bu sayıyı [5.2] olarak değiştirdim ve Rails bana yalnızca 5.1, 5.0 veya 4.2 kullanabileceğimi söyledi. Ben 5.0 ile, sonra 4.2 ile başarı ile denedim.
— Ma

Eski, biliyorum, ancak mevcut kayıtlarınız varsa ekleyin:, null: true:my_table
— jomar

2

Ben her tabloya (varolan bir veritabanı var varsayalım) oluşturulan_at ve updated_at alanları eklemek için arayabilirsiniz basit bir işlev yaptı :

  # 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 (tablo_adı, seçenekler = {}) herkese açık

Tablo_adı'na zaman damgaları (created_at ve updated_at) sütunları ekler. Ek seçenekler (null: false gibi) # add_column öğesine yönlendirilir.

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

1

Önceden cevaplar doğru görünüyor ancak masamın girişleri varsa sorunlarla karşılaştım.

'HATA: sütun değerleri created_atiçerir ' alırım null.

Düzeltmek için kullandım:

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

Sonra taş kullanılan migration_data göç gibi güncel projeler için saat eklemek için:

def data
  Project.update_all created_at: Time.now
end

Bu geçişten sonra oluşturulan tüm projeler doğru şekilde güncellenecektir. Sunucunun da yeniden başlatıldığından emin olun, böylece Rails ActiveRecordkayıttaki zaman damgalarını izlemeye başlar.


1

Burada bir sürü cevap var, ama benimkini de göndereceğim çünkü öncekilerden hiçbiri gerçekten benim için çalışmadı :)

Bazılarının belirttiği gibi, #add_timestampsmaalesef null: falsebu satırları doldurmadıkları için eski satırların geçersiz olmasına neden olacak kısıtlamayı ekler . Çoğu yanıt burada bazı varsayılan değer ( Time.zone.now) ayarlamanızı öneririz , ancak eski veriler için bu varsayılan zaman damgaları doğru olmayacağı için bunu yapmak istemiyorum. Tabloya yanlış veri ekleme değeri görmüyorum.

Bu yüzden göçüm basitçe:

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

Hayır null: false, başka kısıtlama yok. Eski satırlar created_atas NULLve update_atas ile geçerli olmaya devam eder NULL(satıra bir miktar güncelleme yapılana kadar). Yeni satırlar beklendiği gibi doldurulur created_atve updated_atdoldurulur.


1

Buradaki yanıtların çoğuyla ilgili sorun, Time.zone.nowtüm kayıtlara varsayılan olarak geçişin varsayılan zamanları olarak çalıştırıldığı zamana sahip olmasıdır, bu da muhtemelen istediğiniz şey değildir. Raylarda 5 kullanabilirsiniz now(). Bu, geçişin çalıştırıldığı zaman ve yeni eklenen kayıtlar için tamamlama işleminin başlangıç ​​zamanı olarak mevcut kayıtların zaman damgalarını ayarlar.

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


1

Kullanımı Time.currentiyi bir stildir 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

veya

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

Bu, varolan tabloya zaman damgası eklemek için basit bir yöntemdir.

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

0

Rails kullanmayan ancak activerecord kullananlar için, aşağıdakiler mevcut bir modele bir sütun ekler, örnek bir tamsayı alanı içindir.

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

0

O var changedeğil, change_tableRaylar 4.2 için:

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

0

Bu, Rails 5.0.7'de temiz bir çözüm gibi görünüyor (change_column_null yöntemini keşfetti):

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

Rails 5.0'dayım ve bu seçeneklerin hiçbiri işe yaramadı.

İşe yarayan tek şey şu şekilde kullanmaktı: timestamp ve not: datetime

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

-1

Şahsen aşağıdakileri kullandım ve önceki tüm kayıtları güncel saat / tarih ile güncelledi:

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

Aynı sorunu Rails 5 kullanmaya çalıştım

change_table :my_table do |t|
    t.timestamps
end

Zaman damgası sütunlarını aşağıdakilerle manuel olarak ekleyebildim:

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

bu her zaman varsayılan değeri taşıma işleminin yapıldığı saatle ayarlamaz mı? (yani DB tarafından ele alınan dinamik bir zaman damgası değil)
— Guillaume Petit

db'nizde zaten var olan kayıtlar için, evet, oluşturulan_at ve updated_at öğelerini geçişin çalıştırıldığı tarihe ayarlar. Bu değerlere önceden sahip olmadan, bu değerleri başka nasıl başlatacağınızı idk. EDIT: O satır tarihinin başlangıcı olarak kabul edilir
— Andres Rosales
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.