Development Tip

Rails 타임 스탬프 필드의 자동 업데이트를 피할 수있는 방법이 있습니까?

yourdevel 2020. 11. 12. 20:28
반응형

Rails 타임 스탬프 필드의 자동 업데이트를 피할 수있는 방법이 있습니까?


DB 열이 created_at있고 updated_atRails는 모델 객체를 생성하고 업데이트 할 때 해당 값을 자동으로 설정합니다. 해당 열을 건드리지 않고 모델을 저장하는 방법이 있습니까?

일부 레거시 데이터를 가져오고 있으며 (다른 이름의) 레거시 데이터 필드의 해당 값에서 해당 값을 설정하고 싶습니다. 모델에 설정 한 다음 모델을 저장하면 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블록 에서 이전 설정을 복원하는 것을 기억할 필요가 없습니다 .


일회성 가져 오기이므로 다음을 수행 할 수 있습니다.

  1. legacy_created_atlegacy_updated_at필드를 사용하여 모델을 만듭니다 .
  2. 레거시 데이터를로드합니다. 원하는대로 모델 필드에 매핑합니다. 사용할 수 #save있으며 일반적으로 사용 update_all등에 대해 걱정할 필요가 없으며 원하는 경우 콜백을 사용할 수 있습니다.
  3. 마이그레이션을 만들어 열의 이름을 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

참고URL : https://stackoverflow.com/questions/861448/is-there-a-way-to-avoid-automatically-updating-rails-timestamp-fields

반응형