Rails 타임 스탬프 필드의 자동 업데이트를 피할 수있는 방법이 있습니까?
DB 열이 created_at
있고 updated_at
Rails는 모델 객체를 생성하고 업데이트 할 때 해당 값을 자동으로 설정합니다. 해당 열을 건드리지 않고 모델을 저장하는 방법이 있습니까?
일부 레거시 데이터를 가져오고 있으며 (다른 이름의) 레거시 데이터 필드의 해당 값에서 해당 값을 설정하고 싶습니다. 모델에 설정 한 다음 모델을 저장하면 Rails가 들어오는 값을 재정의하는 것처럼 보입니다.
물론이를 방지하기 위해 Rails 모델 열의 이름을 다르게 지정할 수 있지만 데이터를 가져온 후에는 Rails가 자동 타임 스탬프 작업을 수행하기를 원합니다.
마이그레이션 또는 레이크 작업 (또는 에지 레일에있는 경우 새 데이터베이스 시드 에서)에서이 작업을 수행합니다 .
ActiveRecord::Base.record_timestamps = false
begin
run_the_code_that_imports_the_data
ensure
ActiveRecord::Base.record_timestamps = true # don't forget to enable it again!
end
안전하게 설정 created_at
하고 updated_at
수동으로 할 수 있으며 Rails는 불평하지 않습니다.
참고 : 이것은 개별 모델에서도 작동합니다. User.record_timestamps = false
대신 update_column 메소드를 사용하십시오.
http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_column
update_column(name, value)
# Updates a single attribute of an object, without calling save.
유효성 검사를 건너 뜁니다.
콜백을 건너 뜁니다.
해당 열을 사용할 수있는 경우 updated_at / updated_on 열은 업데이트되지 않습니다.
새 개체에서 호출되거나 이름 속성이 읽기 전용으로 표시 될 때 ActiveRecordError를 발생시킵니다.
Rails 5는 타임 스탬프를 업데이트하지 않고 레코드를 업데이트하는 편리한 방법을 제공합니다 updated_at
: https://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-save
touch:false
기록을 업데이트하는 동안 통과하면됩니다 .
>> user = User.first
>> user.updated_at
=> Thu, 28 Apr 2016 20:01:57 IST +05:30
>> user.name = "Jose"
>> user.save(touch: false)
=> true
>> user.updated_at
=> Thu, 28 Apr 2016 20:01:57 IST +05:30
마이그레이션 내에서 다음을 설정할 수 있습니다.
ActiveRecord::Base.record_timestamps = false
또는 대체적으로 update_all을 사용합니다.
update_all (업데이트, 조건 = nil, 옵션 = {})
제공된 조건 세트와 일치하는 경우 제공된 세부 사항으로 모든 레코드를 업데이트합니다. 한계 및 순서도 제공 할 수 있습니다. 이 메서드는 단일 SQL UPDATE 문을 구성하고이를 데이터베이스로 직접 보냅니다. 관련된 모델을 인스턴스화하지 않으며 Active Record 콜백을 트리거하지 않습니다.
Rails 3+에서는 단일 객체에 record_timestamps
대해 클래스가 아닌 객체에 대해 설정 합니다. 즉,
>> user = User.first
>> user.updated_at
=> Tue, 12 Apr 2016 22:47:51 GMT +00:00
>> user.name = "Jose"
=> "Jose"
>> user.record_timestamps = false
>> user.save
=> true
>> user.updated_at
=> Tue, 12 Apr 2016 22:47:51 GMT +00:00
>> User.record_timestamps
=> true
이렇게하면 모델에 대한 전역 상태를 건드리지 않고 ensure
블록 에서 이전 설정을 복원하는 것을 기억할 필요가 없습니다 .
일회성 가져 오기이므로 다음을 수행 할 수 있습니다.
legacy_created_at
및legacy_updated_at
필드를 사용하여 모델을 만듭니다 .- 레거시 데이터를로드합니다. 원하는대로 모델 필드에 매핑합니다. 사용할 수
#save
있으며 일반적으로 사용update_all
등에 대해 걱정할 필요가 없으며 원하는 경우 콜백을 사용할 수 있습니다. - 마이그레이션을 만들어 열의 이름을
created_at
및 로 바꿉니다updated_at
.
믹스 인 모듈을 사용하여 블록에서 타임 스탬프를 일시적으로 끄고 싶습니다.
module WithoutTimestamps
def without_timestamps
old = ActiveRecord::Base.record_timestamps
ActiveRecord::Base.record_timestamps = false
begin
yield
ensure
ActiveRecord::Base.record_timestamps = old
end
end
end
그런 다음 필요할 때마다 사용할 수 있습니다.
class MyModel < ActiveRecord::Base
include WithoutTimestamps
def save_without_timestamps
without_timestamps do
save!
end
end
end
또는 다음과 같은 일회성 :
m = MyModel.find(1)
WithoutTimestamps.without_timestamps do
m.save!
end
대량 가져 오기가 아닌 경우 should_record_timestamps? 모델의 메서드를 사용하여 updated_at 열을 업데이트 할시기에 대한 새 검사를 추가합니다.
다른 답변을 참조하면 다음과 같이 단일 모델에 대한 타임 스탬프를 비활성화하는 것이 놀랍습니다.
User.record_timestamps = false
내 개발 데이터베이스에서 작동했지만 다른 서버에서 실행되는 사전 프로덕션 데이터베이스에서는 작동하지 않았습니다. 그러나 모든 모델에 대해 타임 스탬프를 비활성화하면 작동합니다.
ActiveRecord::Base.record_timestamps = false
(Situation: modifying the created_at attribute in a migration)
Or, for thread safety, see: http://www.hungryfools.com/2007/07/turning-off-activerecord-timestamp.html
I wasn't able to make ActiveRecord::Base.record_timestamps
flag change anything, and the only working way is using ActiveRecord::Base.no_touching {}
:
ActiveRecord::Base.no_touching do
Project.first.touch # does nothing
Message.first.touch # does nothing
end
Project.no_touching do
Project.first.touch # does nothing
Message.first.touch # works, but does not touch the associated project
end
Taken from here.
This is very useful for rake tasks where you have to override some properties of deeply-related models and don't want to bother about inner callbacks, while your users rely on created_at
or updated_at
attributes or those are used as sorting columns.
I'm late to the party but this is how we skip updating updated_at
in my shop:
# config/initializers/no_timestamping.rb
module ActiveRecord
class Base
def update_record_without_timestamping
class << self
def record_timestamps; false; end
end
save!
class << self
remove_method :record_timestamps
end
end
end
end
Usage:
post.something = 'whatever'
post.update_record_without_timestamping
'Development Tip' 카테고리의 다른 글
매개 변수로 암호와 함께 sudo 사용 (0) | 2020.11.12 |
---|---|
Pipenv : 명령을 찾을 수 없음 (0) | 2020.11.12 |
Scala에서 A <: B와 + B의 차이점은 무엇입니까? (0) | 2020.11.12 |
virtualenv에서 "matplotlib.pyplot을 plt로 가져 오기"할 수 없습니다. (0) | 2020.11.12 |
정적 소멸자 (0) | 2020.11.12 |