Module: ActiveRecord::Bitemporal::Persistence
- Includes:
- PersistenceOptionable
- Included in:
- Bitemporalize::InstanceMethods
- Defined in:
- lib/activerecord-bitemporal/bitemporal.rb
Overview
create, update, destroy に処理をフックする
Defined Under Namespace
Modules: EachAssociation, PersistenceOptionable
Instance Method Summary collapse
- #_create_record(attribute_names = self.attribute_names) ⇒ Object
-
#_find_record ⇒ Object
MEMO: Since Rails 7.1 #_find_record refers to a record with find_by!(@primary_key => id) But if @primary_key is “id”, it can’t refer to the intended record, so we hack it to refer to the record based on self.class.bitemporal_id_key see: github.com/rails/rails/blob/v7.1.0/activerecord/lib/active_record/persistence.rb#L1152-#L1171.
- #_update_row(attribute_names, attempted_action = 'update') ⇒ Object
- #destroy(force_delete: false, operated_at: nil) ⇒ Object
- #save ⇒ Object
- #save! ⇒ Object
Methods included from PersistenceOptionable
#bitemporal_at, #bitemporal_option_merge_with_association!, #force_update, #force_update?, #transaction_at, #transaction_datetime, #valid_at, #valid_date, #valid_datetime
Methods included from Optionable
#bitemporal_option, #bitemporal_option_merge!, #with_bitemporal_option
Instance Method Details
#_create_record(attribute_names = self.attribute_names) ⇒ Object
301 302 303 304 305 306 307 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 301 def _create_record(attribute_names = self.attribute_names) bitemporal_assign_initialize_value(valid_datetime: self.valid_datetime) ActiveRecord::Bitemporal.valid_at!(self[valid_from_key]) { super() } end |
#_find_record ⇒ Object
MEMO: Since Rails 7.1 #_find_record refers to a record with find_by!(@primary_key => id)
But if @primary_key is "id", it can't refer to the intended record, so we hack it to refer to the record based on self.class.bitemporal_id_key
see: https://github.com/rails/rails/blob/v7.1.0/activerecord/lib/active_record/persistence.rb#L1152-#L1171
392 393 394 395 396 397 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 392 def _find_record(*) tmp_primary_key, @primary_key = @primary_key, self.class.bitemporal_id_key super ensure @primary_key = tmp_primary_key end |
#_update_row(attribute_names, attempted_action = 'update') ⇒ Object
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 323 def _update_row(attribute_names, attempted_action = 'update') current_valid_record, before_instance, after_instance = bitemporal_build_update_records(valid_datetime: self.valid_datetime, force_update: self.force_update?) # MEMO: このメソッドに来るまでに validation が発動しているので、以後 validate は考慮しなくて大丈夫 ActiveRecord::Base.transaction(requires_new: true) do current_valid_record&.update_transaction_to(current_valid_record.transaction_to) before_instance&.save_without_bitemporal_callbacks!(validate: false) # NOTE: after_instance always exists after_instance.save_without_bitemporal_callbacks!(validate: false) @previously_force_updated = self.force_update? # update 後に新しく生成したインスタンスのデータを移行する @_swapped_id_previously_was = swapped_id @_swapped_id = after_instance.swapped_id self[valid_from_key] = after_instance[valid_from_key] self[valid_to_key] = after_instance[valid_to_key] self.transaction_from = after_instance.transaction_from self.transaction_to = after_instance.transaction_to 1 # MEMO: Must return false instead of nil, if `#_update_row` failure. end || false end |
#destroy(force_delete: false, operated_at: nil) ⇒ Object
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 347 def destroy(force_delete: false, operated_at: nil) return super() if force_delete ActiveRecord::Base.transaction(requires_new: true) do @destroyed = false _run_destroy_callbacks { operated_at ||= Time.current target_datetime = valid_datetime || operated_at duplicated_instance = self.class.find_at_time(target_datetime, self.id).dup @destroyed = update_transaction_to(operated_at) @previously_force_updated = force_update? # force_update の場合は削除時の状態の履歴を残さない unless force_update? # 削除時の状態を履歴レコードとして保存する duplicated_instance[valid_to_key] = target_datetime duplicated_instance.transaction_from = operated_at duplicated_instance.save_without_bitemporal_callbacks!(validate: false) if @destroyed @_swapped_id_previously_was = swapped_id @_swapped_id = duplicated_instance.swapped_id self[valid_from_key] = duplicated_instance[valid_from_key] self[valid_to_key] = duplicated_instance[valid_to_key] self.transaction_from = duplicated_instance.transaction_from self.transaction_to = duplicated_instance.transaction_to end end } raise ActiveRecord::RecordInvalid unless @destroyed self end rescue => e @destroyed = false @_association_destroy_exception = ActiveRecord::RecordNotDestroyed.new("Failed to destroy the record: class=#{e.class}, message=#{e.message}", self) @_association_destroy_exception.set_backtrace(e.backtrace) false end |
#save ⇒ Object
309 310 311 312 313 314 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 309 def save(**) ActiveRecord::Base.transaction(requires_new: true) do self.class.where(bitemporal_id: self.id).lock!.pluck(:id) if self.id super end end |
#save! ⇒ Object
316 317 318 319 320 321 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 316 def save!(**) ActiveRecord::Base.transaction(requires_new: true) do self.class.where(bitemporal_id: self.id).lock!.pluck(:id) if self.id super end end |