Class: Hold::Sequel::IdentitySetRepository::WithPolymorphicTypeColumn
- Inherits:
-
Hold::Sequel::IdentitySetRepository
- Object
- Hold::Sequel::IdentitySetRepository
- Hold::Sequel::IdentitySetRepository::WithPolymorphicTypeColumn
- Defined in:
- lib/hold/sequel/with_polymorphic_type_column.rb
Overview
Subclass of Sequel::IdentitySetRepository which adds support for a polymorphic type column which is used to persist the class of the model.
Constant Summary
Constants inherited from Hold::Sequel::IdentitySetRepository
Instance Attribute Summary
Attributes inherited from Hold::Sequel::IdentitySetRepository
#db, #default_properties, #id_sequence_table, #identity_mapper, #identity_property, #main_table, #property_mappers
Class Method Summary collapse
- .class_to_type_mapping ⇒ Object
- .restricted_to_types ⇒ Object
- .supported_classes ⇒ Object
- .type_column ⇒ Object
- .type_column_table ⇒ Object
- .type_to_class_mapping ⇒ Object
Instance Method Summary collapse
-
#can_construct_from_id_alone?(properties) ⇒ Boolean
This optimisation has to be turned off for polymorphic repositories, since even if we know the ID, we have to query the db to find out the appropriate class to construct the object as.
- #can_get_class?(model_class) ⇒ Boolean
- #can_set_class?(model_class) ⇒ Boolean
-
#columns_aliases_and_tables_for_properties(properties) ⇒ Object
ensure we select the type column in addition to any columns for mapped properties, so we know which class to instantiate for each row.
- #construct_entity(property_hash, row = nil) ⇒ Object
-
#dataset_to_select_tables(*tables) ⇒ Object
Where ‘restricted_to_types’ has been set, ensure we add a filter to the where clause restricting to rows with the allowed class (or classes).
-
#initialize(db) ⇒ WithPolymorphicTypeColumn
constructor
A new instance of WithPolymorphicTypeColumn.
Methods inherited from Hold::Sequel::IdentitySetRepository
#add_observer, #allocates_ids?, #array_cell_for_dataset, #construct_entity_from_id, constructor_dependencies, #contains?, #contains_id?, #count_dataset, #delete, #delete_id, #get_all, #get_by_id, #get_by_property, #get_many_by_ids, #get_many_by_property, #get_many_with_dataset, #get_property, #get_repo_dependencies_from, #get_with_dataset, inject_dependency, #inspect, #mapper, #model_class, model_class, new_from_dependencies, #post_delete, #post_insert, #post_update, #pre_delete, #pre_insert, #pre_update, property_mapper_args, provides_class, provides_features, #query, setter_dependencies, #store, #store_new, #table_id_column, tables, #transaction, #update, #update_by_id
Methods included from IdentitySetRepository
#allocates_ids?, #cell, #contains_id?, #delete_id, #get_by_id, #get_many_by_ids, #id_cell, #load, #reload, #update, #update_by_id
Methods included from Hold::SetRepository
#contains?, #delete, #get_all, #store, #store_new
Constructor Details
#initialize(db) ⇒ WithPolymorphicTypeColumn
Returns a new instance of WithPolymorphicTypeColumn.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/hold/sequel/with_polymorphic_type_column.rb', line 74 def initialize(db) super @qualified_type_column = ::Sequel::SQL::QualifiedIdentifier.new(self.class.type_column_table, self.class.type_column) @aliased_type_column = ::Sequel::SQL::AliasedExpression.new(@qualified_type_column, :type) @restricted_to_types = self.class.restricted_to_types @tables_restricting_type = {} self.class.tables.each do |name, | @tables_restricting_type[name] = true if [:restricts_type] end end |
Class Method Details
.class_to_type_mapping ⇒ Object
16 17 18 19 20 21 |
# File 'lib/hold/sequel/with_polymorphic_type_column.rb', line 16 def class_to_type_mapping @class_to_type_mapping ||= if superclass < WithPolymorphicTypeColumn superclass.class_to_type_mapping end end |
.restricted_to_types ⇒ Object
30 31 32 33 34 35 |
# File 'lib/hold/sequel/with_polymorphic_type_column.rb', line 30 def restricted_to_types @restricted_to_types ||= if superclass < WithPolymorphicTypeColumn superclass.restricted_to_types end end |
.supported_classes ⇒ Object
37 38 39 40 41 42 43 |
# File 'lib/hold/sequel/with_polymorphic_type_column.rb', line 37 def supported_classes if restricted_to_types type_to_class_mapping.values_at(*restricted_to_types) else class_to_type_mapping.keys end end |
.type_column ⇒ Object
8 9 10 |
# File 'lib/hold/sequel/with_polymorphic_type_column.rb', line 8 def type_column @type_column ||= superclass.type_column end |
.type_column_table ⇒ Object
12 13 14 |
# File 'lib/hold/sequel/with_polymorphic_type_column.rb', line 12 def type_column_table @type_column_table ||= superclass.type_column_table end |
.type_to_class_mapping ⇒ Object
23 24 25 26 27 28 |
# File 'lib/hold/sequel/with_polymorphic_type_column.rb', line 23 def type_to_class_mapping @type_to_class_mapping ||= if superclass < WithPolymorphicTypeColumn superclass.type_to_class_mapping end end |
Instance Method Details
#can_construct_from_id_alone?(properties) ⇒ Boolean
This optimisation has to be turned off for polymorphic repositories, since even if we know the ID, we have to query the db to find out the appropriate class to construct the object as.
110 111 112 |
# File 'lib/hold/sequel/with_polymorphic_type_column.rb', line 110 def can_construct_from_id_alone?(properties) super && @restricted_to_types && @restricted_to_types.length == 1 end |
#can_get_class?(model_class) ⇒ Boolean
90 91 92 |
# File 'lib/hold/sequel/with_polymorphic_type_column.rb', line 90 def can_get_class?(model_class) self.class.supported_classes.include?(model_class) end |
#can_set_class?(model_class) ⇒ Boolean
94 95 96 |
# File 'lib/hold/sequel/with_polymorphic_type_column.rb', line 94 def can_set_class?(model_class) self.class.supported_classes.include?(model_class) end |
#columns_aliases_and_tables_for_properties(properties) ⇒ Object
ensure we select the type column in addition to any columns for mapped properties, so we know which class to instantiate for each row.
If we’re restricted to only one class, we don’t need to select the type column
119 120 121 122 123 124 125 126 127 128 |
# File 'lib/hold/sequel/with_polymorphic_type_column.rb', line 119 def columns_aliases_and_tables_for_properties(properties) columns_by_property, aliased_columns, tables = super unless @restricted_to_types && @restricted_to_types.length == 1 aliased_columns << @aliased_type_column unless tables.include?(self.class.type_column_table) tables << self.class.type_column_table end end [columns_by_property, aliased_columns, tables] end |
#construct_entity(property_hash, row = nil) ⇒ Object
98 99 100 101 102 103 104 105 |
# File 'lib/hold/sequel/with_polymorphic_type_column.rb', line 98 def construct_entity(property_hash, row = nil) type_value = row && row[:type] || (return super) klass = self.class.type_to_class_mapping[type_value] || (fail "WithPolymorphicTypeColumn: type column value #{type_value}" \ ' not found in mapping') klass.new(property_hash) end |
#dataset_to_select_tables(*tables) ⇒ Object
Where ‘restricted_to_types’ has been set, ensure we add a filter to the where clause restricting to rows with the allowed class (or classes).
Except, where one of the tables used is specified in this repo’s config as :restricts_type => true, this is taken to mean that (inner) joining to this table effectively acts as this repo’s restricted_to_types restriction. hence no additional where clause is needed in order to do this. Helps with Class Table Inheritance.
139 140 141 142 143 144 145 146 |
# File 'lib/hold/sequel/with_polymorphic_type_column.rb', line 139 def dataset_to_select_tables(*tables) if @restricted_to_types && !@tables_restricting_type.values_at(*tables).any? super.filter(@qualified_type_column => @restricted_to_types) else super end end |