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
343 344 345 346 347 348 349 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 343 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
433 434 435 436 437 438 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 433 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
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 365 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
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 389 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.}", self) @_association_destroy_exception.set_backtrace(e.backtrace) false end |
#save ⇒ Object
351 352 353 354 355 356 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 351 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
358 359 360 361 362 363 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 358 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 |