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: https://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
313 314 315 316 317 318 319 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 313 def _create_record(attribute_names = self.attribute_names) bitemporal_assign_initialize_value(valid_datetime: self.valid_datetime) ActiveRecord::Bitemporal.valid_at!(self.valid_from) { 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
403 404 405 406 407 408 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 403 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
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 335 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 = after_instance.valid_from self.valid_to = after_instance.valid_to 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
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 387 388 389 390 391 392 393 394 395 396 397 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 359 def destroy(force_delete: false, operated_at: nil) return super() if force_delete ActiveRecord::Base.transaction(requires_new: true, joinable: false) 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 = 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 = duplicated_instance.valid_from self.valid_to = duplicated_instance.valid_to 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) false end |
#save ⇒ Object
321 322 323 324 325 326 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 321 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
328 329 330 331 332 333 |
# File 'lib/activerecord-bitemporal/bitemporal.rb', line 328 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 |