Yanıtlar:
Zaman damgası yardımcısı yalnızca create_table
blokta 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_timestamps
yukarı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.
rails g migration AddTimestampsToUser created_at:datetime updated_at:datetime
- yukarıdaki taşımayı oluşturmak için bir kısayol.
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.
add_column :users, :updated_at, :datetime, null: false, default: Time.zone.now
. Time.zone.now
sadece bir örnek, mantığınız için anlamlı olan her değeri kullanmalısınız.
Taşıma işlemleri yalnızca iki sınıf yöntemidir (veya 3.1'deki örnek yöntemler): up
ve down
(ve bazen change
3.1'deki bir örnek yöntemidir). Değişikliklerinizin up
yö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_table
ve change_table
.
Daha fazla ayrıntı için taşıma kılavuzuna bakın.
change
şimdi yöntem var, ancak bu durumda, sorun değil :)
change
bahsetmeye değer, bu yüzden ben de ekleyeceğim.
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 change
yerine 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 up
ve down
yöntemleriniz gerekir change_table
:
class AddTimestampsToUser < ActiveRecord::Migration
def up
add_timestamps(:users)
end
def down
remove_timestamps(:users)
end
end
@ 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.
Time.zone.now
kodumuzun doğru saat dilimine uymasını istiyorsak ne kullanmamız gerektiğidir.
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.
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
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::IrreversibleMigration
a 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
change_column_default
desteklemiyor 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ı! from
to
up/down
change
def change
add_timestamps :table_name
end
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 .
, null: true
:my_table
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
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
Ö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_at
iç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 ActiveRecord
kayıttaki zaman damgalarını izlemeye başlar.
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_timestamps
maalesef null: false
bu 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_at
as NULL
ve update_at
as ile geçerli olmaya devam eder NULL
(satıra bir miktar güncelleme yapılana kadar). Yeni satırlar beklendiği gibi doldurulur created_at
ve updated_at
doldurulur.
Buradaki yanıtların çoğuyla ilgili sorun, Time.zone.now
tü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
Kullanımı Time.current
iyi 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
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
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
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
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