Class: ViewModel::ActiveRecord::UpdateData
- Inherits:
-
Object
- Object
- ViewModel::ActiveRecord::UpdateData
- Defined in:
- lib/view_model/active_record/update_data.rb
Defined Under Namespace
Modules: Schemas
Instance Attribute Summary collapse
-
#associations ⇒ Object
Returns the value of attribute associations.
-
#attributes ⇒ Object
Returns the value of attribute attributes.
-
#metadata ⇒ Object
Returns the value of attribute metadata.
-
#referenced_associations ⇒ Object
Returns the value of attribute referenced_associations.
-
#viewmodel_class ⇒ Object
Returns the value of attribute viewmodel_class.
Class Method Summary collapse
- .check_duplicate_updates(updates, type:) ⇒ Object
- .empty_update_for(viewmodel) ⇒ Object
- .parse_associated(association_data, blame_reference, valid_reference_keys, child_hash) ⇒ Object
- .parse_hashes(root_subtree_hashes, referenced_subtree_hashes = {}) ⇒ Object
Instance Method Summary collapse
- #[](name) ⇒ Object
- #build_preload_specs(association_data, updates) ⇒ Object
- #has_key?(name) ⇒ Boolean
-
#initialize(viewmodel_class, metadata, hash_data, valid_reference_keys) ⇒ UpdateData
constructor
A new instance of UpdateData.
- #merge_preload_specs(association_data, specs) ⇒ Object
-
#preload_dependencies ⇒ Object
Updates in terms of activerecord associations: used for preloading subtree associations necessary to perform update.
- #reference_only? ⇒ Boolean
-
#to_sequence(name, value) ⇒ Object
Produce a sequence of update datas for a given association update value, in the spirit of Array.wrap.
- #viewmodel_reference ⇒ Object
Constructor Details
#initialize(viewmodel_class, metadata, hash_data, valid_reference_keys) ⇒ UpdateData
Returns a new instance of UpdateData.
571 572 573 574 575 576 577 578 579 |
# File 'lib/view_model/active_record/update_data.rb', line 571 def initialize(viewmodel_class, , hash_data, valid_reference_keys) self.viewmodel_class = viewmodel_class self. = self.attributes = {} self.associations = {} self.referenced_associations = {} parse(hash_data, valid_reference_keys) end |
Instance Attribute Details
#associations ⇒ Object
Returns the value of attribute associations.
396 397 398 |
# File 'lib/view_model/active_record/update_data.rb', line 396 def associations @associations end |
#attributes ⇒ Object
Returns the value of attribute attributes.
396 397 398 |
# File 'lib/view_model/active_record/update_data.rb', line 396 def attributes @attributes end |
#metadata ⇒ Object
Returns the value of attribute metadata.
396 397 398 |
# File 'lib/view_model/active_record/update_data.rb', line 396 def @metadata end |
#referenced_associations ⇒ Object
Returns the value of attribute referenced_associations.
396 397 398 |
# File 'lib/view_model/active_record/update_data.rb', line 396 def referenced_associations @referenced_associations end |
#viewmodel_class ⇒ Object
Returns the value of attribute viewmodel_class.
396 397 398 |
# File 'lib/view_model/active_record/update_data.rb', line 396 def viewmodel_class @viewmodel_class end |
Class Method Details
.check_duplicate_updates(updates, type:) ⇒ Object
563 564 565 566 567 568 569 |
# File 'lib/view_model/active_record/update_data.rb', line 563 def self.check_duplicate_updates(updates, type:) # Ensure that no root is referred to more than once duplicates = updates.duplicates_by { |upd| upd.viewmodel_reference if upd.id } if duplicates.present? raise ViewModel::DeserializationError::DuplicateNodes.new(type, duplicates.keys) end end |
.empty_update_for(viewmodel) ⇒ Object
581 582 583 584 |
# File 'lib/view_model/active_record/update_data.rb', line 581 def self.empty_update_for(viewmodel) = ViewModel::Metadata.new(viewmodel.id, viewmodel.view_name, viewmodel.class.schema_version, false) self.new(viewmodel.class, , {}, []) end |
.parse_associated(association_data, blame_reference, valid_reference_keys, child_hash) ⇒ Object
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 |
# File 'lib/view_model/active_record/update_data.rb', line 645 def self.parse_associated(association_data, blame_reference, valid_reference_keys, child_hash) = ViewModel.(child_hash) child_viewmodel_class = association_data.viewmodel_class_for_name(.view_name) if child_viewmodel_class.nil? raise ViewModel::DeserializationError::InvalidAssociationType.new( association_data.association_name.to_s, .view_name, blame_reference) end verify_schema_version!(child_viewmodel_class, .schema_version, .id) if .schema_version UpdateData.new(child_viewmodel_class, , child_hash, valid_reference_keys) end |
.parse_hashes(root_subtree_hashes, referenced_subtree_hashes = {}) ⇒ Object
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 |
# File 'lib/view_model/active_record/update_data.rb', line 529 def self.parse_hashes(root_subtree_hashes, referenced_subtree_hashes = {}) valid_reference_keys = referenced_subtree_hashes.keys.to_set valid_reference_keys.each do |ref| unless ref.is_a?(String) raise ViewModel::DeserializationError::InvalidSyntax.new("Invalid reference string: #{ref}") end end # Construct root UpdateData root_updates = root_subtree_hashes.map do |subtree_hash| = ViewModel.(subtree_hash) viewmodel_class = ViewModel::Registry.for_view_name(.view_name) verify_schema_version!(viewmodel_class, .schema_version, .id) if .schema_version UpdateData.new(viewmodel_class, , subtree_hash, valid_reference_keys) end # Ensure that no root is referred to more than once check_duplicate_updates(root_updates, type: 'root') # Construct reference UpdateData referenced_updates = referenced_subtree_hashes.transform_values do |subtree_hash| = ViewModel.(subtree_hash) viewmodel_class = ViewModel::Registry.for_view_name(.view_name) verify_schema_version!(viewmodel_class, .schema_version, .id) if .schema_version UpdateData.new(viewmodel_class, , subtree_hash, valid_reference_keys) end check_duplicate_updates(referenced_updates.values, type: 'reference') return root_updates, referenced_updates end |
Instance Method Details
#[](name) ⇒ Object
503 504 505 506 507 508 509 510 511 512 |
# File 'lib/view_model/active_record/update_data.rb', line 503 def [](name) case name when :id id when :_type viewmodel_class.view_name else attributes.fetch(name) { associations.fetch(name) { referenced_associations.fetch(name) } } end end |
#build_preload_specs(association_data, updates) ⇒ Object
601 602 603 604 605 606 607 608 609 610 611 |
# File 'lib/view_model/active_record/update_data.rb', line 601 def build_preload_specs(association_data, updates) if association_data.polymorphic? updates.map do |update_data| target_model = update_data.viewmodel_class.model_class DeepPreloader::PolymorphicSpec.new( target_model.name => update_data.preload_dependencies) end else updates.map { |update_data| update_data.preload_dependencies } end end |
#has_key?(name) ⇒ Boolean
514 515 516 517 518 519 520 521 |
# File 'lib/view_model/active_record/update_data.rb', line 514 def has_key?(name) case name when :id, :_type true else attributes.has_key?(name) || associations.has_key?(name) || referenced_associations.has_key?(name) end end |
#merge_preload_specs(association_data, specs) ⇒ Object
613 614 615 616 |
# File 'lib/view_model/active_record/update_data.rb', line 613 def merge_preload_specs(association_data, specs) empty = association_data.polymorphic? ? DeepPreloader::PolymorphicSpec.new : DeepPreloader::Spec.new specs.inject(empty) { |acc, spec| acc.merge!(spec) } end |
#preload_dependencies ⇒ Object
Updates in terms of activerecord associations: used for preloading subtree associations necessary to perform update.
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 |
# File 'lib/view_model/active_record/update_data.rb', line 620 def preload_dependencies deps = {} associations.merge(referenced_associations).each do |assoc_name, reference| association_data = self.viewmodel_class._association_data(assoc_name) preload_specs = build_preload_specs(association_data, to_sequence(assoc_name, reference)) referenced_deps = merge_preload_specs(association_data, preload_specs) if association_data.through? referenced_deps = DeepPreloader::Spec.new(association_data.indirect_reflection.name.to_s => referenced_deps) end deps[association_data.direct_reflection.name.to_s] = referenced_deps end DeepPreloader::Spec.new(deps) end |
#reference_only? ⇒ Boolean
525 526 527 |
# File 'lib/view_model/active_record/update_data.rb', line 525 def reference_only? attributes.empty? && associations.empty? && referenced_associations.empty? end |
#to_sequence(name, value) ⇒ Object
Produce a sequence of update datas for a given association update value, in the spirit of Array.wrap.
587 588 589 590 591 592 593 594 595 596 597 598 599 |
# File 'lib/view_model/active_record/update_data.rb', line 587 def to_sequence(name, value) association_data = self.viewmodel_class._association_data(name) case when value.nil? [] when association_data.referenced? [] when association_data.collection? # nested, because of referenced? check above value.update_datas else [value] end end |