답변:
타임 스탬프 도우미는 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
테이블에 null 제약 조건을 위반하지 않는 데이터가 이미 포함되어 있기 때문에이 마이그레이션을 실행하면 오류가 발생 합니다. 처음에는 null이 아닌 제약 조건을 제거한 다음 나중에 추가하는 것보다 더 좋은 방법은 무엇입니까?
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
Dave를 사용할 수도 있습니다 .
class AddTimestampsToUser < ActiveRecord::Migration
def change
change_table(:users) { |t| t.timestamps }
end
end
아마 당신은 혼란하고 def change
, def change_table
하고 change_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 : 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
마이그레이션을 실행할 때 생성 된 Time 인스턴스를 반환하고 해당 시간을 기본값으로 사용한다는 기본값을 설정하는 데 문제 가 있습니다. 새로운 객체는 새로운 Time 인스턴스를 얻지 못합니다.
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::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
change_column_default
지원하지 않습니다 from
및 to
해당 버전에?),하지만이 아이디어를 가져다가 만든 up/down
대신 하나의 방법 change
방법과 마법처럼 일했다!
이것이 정확히 언제 도입되었는지 확실하지 않지만 레일 5.2.1에서 다음을 수행 할 수 있습니다.
class AddTimestampsToMyTable < ActiveRecord::Migration[5.2]
def change
add_timestamps :my_table
end
end
, null: true
애프터:my_table
이전 답변은 옳은 것처럼 보이지만 테이블에 이미 항목이 있으면 문제가 발생했습니다.
'오류 : 열에 값이 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
as NULL
및 update_at
as 로 계속 유효 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
이것은 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
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