ฉันต้องการเพิ่มการประทับเวลา ( created_at& updated_at) ลงในตารางที่มีอยู่ ฉันลองใช้รหัสต่อไปนี้ แต่มันไม่ทำงาน
class AddTimestampsToUser < ActiveRecord::Migration
    def change_table
        add_timestamps(:users)
    end
end
          ฉันต้องการเพิ่มการประทับเวลา ( created_at& updated_at) ลงในตารางที่มีอยู่ ฉันลองใช้รหัสต่อไปนี้ แต่มันไม่ทำงาน
class AddTimestampsToUser < ActiveRecord::Migration
    def change_table
        add_timestamps(:users)
    end
end
          คำตอบ:
ตัวช่วยประทับเวลาจะมีเฉพาะใน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คุณได้ระบุไว้ข้างต้น แต่ Rails จะยังคงปฏิบัติต่อคอลัมน์เหล่านี้เป็นคอลัมน์ประทับเวลาและอัปเดตค่าตามปกติ
rails g migration AddTimestampsToUser created_at:datetime updated_at:datetime- ทางลัดเพื่อสร้างการย้ายข้อมูลข้างต้น
                    PG::NotNullViolation: ERROR:  column "created_at" contains null value   เนื่องจากตารางของฉันมีข้อมูลที่ละเมิดข้อ จำกัด ที่ไม่มีค่าว่างอยู่แล้ว มีวิธีใดที่ดีกว่าในการทำเช่นนี้แทนที่จะลบข้อ จำกัด ที่ไม่ใช่โมฆะในตอนแรกจากนั้นจึงเพิ่มในภายหลัง
                    add_column :users, :updated_at, :datetime, null: false, default: Time.zone.nowขึ้นอยู่กับสิ่งที่คุณคิดว่าเหมาะสมที่สุดสำหรับค่าเริ่มต้นที่คุณสามารถทำได้ Time.zone.nowเป็นเพียงตัวอย่างคุณควรใช้ค่าใด ๆ ที่สมเหตุสมผลกับตรรกะของคุณ
                    การย้ายข้อมูลเป็นเพียงวิธีการเรียนสองวิธี (หรือวิธีการตัวอย่างใน 3.1): upและdown(และบางครั้งเป็นchangeวิธีการตัวอย่างใน 3.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_tablechange_table
ดูคู่มือการโยกย้ายสำหรับรายละเอียดเพิ่มเติม
changeวิธีการในขณะนี้แม้ว่าในกรณีนี้ไม่เป็นปัญหา :)
                    changeมีมูลค่าการกล่าวถึงดังนั้นฉันจะเพิ่มที่เกินไป
                    รหัสต้นฉบับของคุณใกล้ด้านขวาคุณเพียงแค่ต้องใช้ชื่อวิธีอื่น หากคุณใช้ Rails 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
              การตอบสนองของ @ user1899434 เกิดขึ้นจากข้อเท็จจริงที่ว่าตาราง "ที่มีอยู่" ที่นี่อาจหมายถึงตารางที่มีระเบียนอยู่ในนั้นแล้วบันทึกที่คุณอาจไม่ต้องการวาง ดังนั้นเมื่อคุณเพิ่มการประทับเวลาด้วย null: false ซึ่งเป็นค่าเริ่มต้นและมักเป็นที่ต้องการบันทึกที่มีอยู่เหล่านั้นจะไม่ถูกต้องทั้งหมด
แต่ฉันคิดว่าคำตอบนั้นสามารถปรับปรุงได้โดยการรวมสองขั้นตอนเข้าด้วยกันในการโยกย้ายครั้งเดียวรวมทั้งใช้เมธอด 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ได้เช่นถ้าคุณต้องการให้มีการสร้าง / อัปเดตระเบียนที่มีมาก่อนในตอนเช้าแทน
Time.zone.nowเป็นสิ่งที่ควรใช้ถ้าเราต้องการให้รหัสของเราเป็นไปตามเขตเวลาที่ถูกต้อง
                    Time.zone.nowซึ่งจะส่งคืนอินสแตนซ์เวลาที่สร้างขึ้นเมื่อมีการเรียกใช้การย้ายข้อมูลและใช้เวลานั้นเป็นค่าเริ่มต้น วัตถุใหม่จะไม่ได้รับอินสแตนซ์เวลาใหม่
                    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
คำตอบของ Nick Daviesนั้นสมบูรณ์ที่สุดในแง่ของการเพิ่มคอลัมน์ประทับเวลาลงในตารางที่มีข้อมูลที่มีอยู่ เสียเพียงอย่างเดียวของมันคือมันจะขึ้นอยู่กับActiveRecord::IrreversibleMigrationdb: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
              change_column_defaultไม่รองรับfromและtoในเวอร์ชั่นนั้น) แต่ฉันใช้ความคิดนี้และสร้างup/downวิธีการแทนวิธีการเดียวchangeและใช้งานได้ดี!
                    def change
  add_timestamps :table_name
end
              ไม่แน่ใจว่าสิ่งนี้ถูกนำมาใช้อย่างแน่นอน แต่ในทางรถไฟ 5.2.1 คุณสามารถทำได้:
class AddTimestampsToMyTable < ActiveRecord::Migration[5.2]
  def change
    add_timestamps :my_table
  end
end
เพื่อดูเพิ่มเติม " ใช้วิธีการเปลี่ยนแปลง " ในเอกสารการโยกย้ายบันทึกที่ใช้งานอยู่
, null: trueหลังจาก:my_table
                    ฉันได้สร้างฟังก์ชั่นง่าย ๆ ที่คุณสามารถเรียกเพื่อเพิ่มไปยังแต่ละตาราง (สมมติว่าคุณมีฐานข้อมูลที่มีอยู่) เขตข้อมูล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
              add_timestamps (table_name, options = {}) พับลิก
เพิ่มคอลัมน์การประทับเวลา (created_at และ updated_at) ลงใน table_name ตัวเลือกเพิ่มเติม (เช่น null: false) จะถูกส่งต่อไปยัง #add_column
class AddTimestampsToUsers < ActiveRecord::Migration
  def change
    add_timestamps(:users, null: false)
  end
end
              คำตอบก่อนที่จะดูเหมือนจะถูก แต่ฉันประสบปัญหาหากตารางของฉันมีรายการแล้ว
ฉันจะได้รับ 'ข้อผิดพลาด: คอลัมน์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
จากนั้นฉันใช้ gem migration_dataเพื่อเพิ่มเวลาสำหรับโครงการปัจจุบันในการย้ายข้อมูลเช่น:
def data
  Project.update_all created_at: Time.now
end
จากนั้นโครงการทั้งหมดที่สร้างหลังจากการโยกย้ายนี้จะได้รับการปรับปรุงอย่างถูกต้อง ตรวจสอบให้แน่ใจว่ามีการรีสตาร์ทเซิร์ฟเวอร์ด้วยเพื่อให้ Rails ActiveRecordเริ่มติดตามการประทับเวลาในบันทึก
มีคำตอบมากมายที่นี่ แต่ฉันจะโพสต์ของฉันด้วยเพราะไม่มีคำตอบก่อนหน้านี้ที่เหมาะกับฉันจริงๆ :)
ตามที่บางคนระบุไว้#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เติมตามที่คาดไว้
ปัญหาของคำตอบส่วนใหญ่ที่นี่คือถ้าคุณเริ่มต้นTime.zone.nowระเบียนทั้งหมดจะมีเวลาที่การโยกย้ายถูกเรียกใช้เป็นเวลาเริ่มต้นซึ่งอาจไม่ใช่สิ่งที่คุณต้องการ ในราง 5 now()คุณสามารถใช้แทน สิ่งนี้จะตั้งค่าการประทับเวลาสำหรับบันทึกที่มีอยู่เป็นเวลาที่การโยกย้ายถูกเรียกใช้และเป็นเวลาเริ่มต้นของการทำธุรกรรมการกระทำสำหรับการแทรกระเบียนใหม่
class AddTimestampsToUsers < ActiveRecord::Migration
  def change
    add_timestamps :users, default: -> { 'now()' }, null: false
  end
end
การใช้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
              นี่เป็นวิธีง่ายๆในการเพิ่มการประทับเวลาในตารางที่มีอยู่
class AddTimeStampToCustomFieldMeatadata < ActiveRecord::Migration
  def change
    add_timestamps :custom_field_metadata
  end
end
              สำหรับผู้ที่ไม่ได้ใช้ Rails แต่ใช้ activerecord ต่อไปนี้จะเพิ่มคอลัมน์ในโมเดลที่มีอยู่ตัวอย่างเช่นสำหรับฟิลด์จำนวนเต็ม
ActiveRecord::Schema.define do
  change_table 'MYTABLE' do |table|
    add_column(:mytable, :my_field_name, :integer)
  end
end
              มันchangeไม่ใช่change_tableสำหรับ Rails 4.2:
class AddTimestampsToUsers < ActiveRecord::Migration
  def change
    add_timestamps(:users)
  end
end
              ดูเหมือนว่าวิธีแก้ปัญหาแบบสะอาดใน Rails 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
              ฉันอยู่บนราง 5.0 และตัวเลือกเหล่านี้ไม่ทำงาน
สิ่งเดียวที่ทำงานได้คือใช้ชนิดเป็น: timestamp และไม่ใช่: datetime
def change
    add_column :users, :created_at, :timestamp
    add_column :users, :updated_at, :timestamp
end
              ฉันใช้สิ่งต่อไปนี้เป็นการส่วนตัวและปรับปรุงระเบียนก่อนหน้าทั้งหมดด้วยเวลา / วันที่ปัจจุบัน:
add_column :<table>, :created_at, :datetime, default: Time.zone.now, null: false
add_column :<table>, :updated_at, :datetime, default: Time.zone.now, null: false
              ฉันพบปัญหาเดียวกันกับ Rails 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