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
- #new? ⇒ Boolean
-
#preload_dependencies ⇒ Object
Updates in terms of activerecord associations: used for preloading subtree associations necessary to perform update.
-
#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.
565 566 567 568 569 570 571 572 573 |
# File 'lib/view_model/active_record/update_data.rb', line 565 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.
392 393 394 |
# File 'lib/view_model/active_record/update_data.rb', line 392 def associations @associations end |
#attributes ⇒ Object
Returns the value of attribute attributes.
392 393 394 |
# File 'lib/view_model/active_record/update_data.rb', line 392 def attributes @attributes end |
#metadata ⇒ Object
Returns the value of attribute metadata.
392 393 394 |
# File 'lib/view_model/active_record/update_data.rb', line 392 def end |
#referenced_associations ⇒ Object
Returns the value of attribute referenced_associations.
392 393 394 |
# File 'lib/view_model/active_record/update_data.rb', line 392 def referenced_associations @referenced_associations end |
#viewmodel_class ⇒ Object
Returns the value of attribute viewmodel_class.
392 393 394 |
# File 'lib/view_model/active_record/update_data.rb', line 392 def viewmodel_class @viewmodel_class end |
Class Method Details
.check_duplicate_updates(updates, type:) ⇒ Object
557 558 559 560 561 562 563 |
# File 'lib/view_model/active_record/update_data.rb', line 557 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
575 576 577 578 |
# File 'lib/view_model/active_record/update_data.rb', line 575 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
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 |
# File 'lib/view_model/active_record/update_data.rb', line 639 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
523 524 525 526 527 528 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 |
# File 'lib/view_model/active_record/update_data.rb', line 523 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
499 500 501 502 503 504 505 506 507 508 |
# File 'lib/view_model/active_record/update_data.rb', line 499 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
595 596 597 598 599 600 601 602 603 604 605 |
# File 'lib/view_model/active_record/update_data.rb', line 595 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
510 511 512 513 514 515 516 517 |
# File 'lib/view_model/active_record/update_data.rb', line 510 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
607 608 609 610 |
# File 'lib/view_model/active_record/update_data.rb', line 607 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 |
#new? ⇒ Boolean
519 520 521 |
# File 'lib/view_model/active_record/update_data.rb', line 519 def new? id.nil? || .new? end |
#preload_dependencies ⇒ Object
Updates in terms of activerecord associations: used for preloading subtree associations necessary to perform update.
614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 |
# File 'lib/view_model/active_record/update_data.rb', line 614 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 |
#to_sequence(name, value) ⇒ Object
Produce a sequence of update datas for a given association update value, in the spirit of Array.wrap.
581 582 583 584 585 586 587 588 589 590 591 592 593 |
# File 'lib/view_model/active_record/update_data.rb', line 581 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 |
#viewmodel_reference ⇒ Object
635 636 637 |
# File 'lib/view_model/active_record/update_data.rb', line 635 def viewmodel_reference ViewModel::Reference.new(viewmodel_class, id) end |