# File lib/torque/postgresql/inheritance.rb, line 118 def primary_key return super unless physically_inherited? superclass.primary_key end
module Torque::PostgreSQL::Inheritance::ClassMethods
Public Instance Methods
For all main purposes, physical inherited classes should have base_class
as their own
# File lib/torque/postgresql/inheritance.rb, line 111 def base_class return super unless physically_inherited? self end
Get the list of all ActiveRecord
classes directly or indirectly associated by inheritance
# File lib/torque/postgresql/inheritance.rb, line 78 def casted_dependents @casted_dependents ||= inheritance_dependents.map do |table_name| [table_name, connection.schema_cache.lookup_model(table_name)] end.to_h end
Add an additional check to return the name of the table even when the class is inherited, but only if it is a physical inheritance
# File lib/torque/postgresql/inheritance.rb, line 125 def compute_table_name return super unless physically_inherited? decorated_table_name end
Get the final decorated table, regardless of any special condition
# File lib/torque/postgresql/inheritance.rb, line 98 def decorated_table_name parent_class = try(:module_parent) || try(:parent) if parent_class < Base && !parent_class.abstract_class? contained = parent_class.table_name contained = contained.singularize if parent_class.pluralize_table_names contained += "_" end "#{full_table_name_prefix}#{contained}#{undecorated_table_name(name)}#{full_table_name_suffix}" end
Get the list of all tables directly or indirectly dependent of the current one
# File lib/torque/postgresql/inheritance.rb, line 67 def inheritance_dependents connection.schema_cache.associations(table_name) || [] end
Get the list of attributes that can be merged while querying because they all have the same type
# File lib/torque/postgresql/inheritance.rb, line 37 def inheritance_mergeable_attributes @inheritance_mergeable_attributes ||= begin base = inheritance_merged_attributes - attribute_names types = base.zip(base.size.times.map { [] }).to_h casted_dependents.values.each do |klass| klass.attribute_types.each do |column, type| types[column]&.push(type) end end result = types.select do |_, types| types.each_with_object(types.shift).all?(&:==) end.keys + attribute_names result.freeze end end
Get a full list of all attributes from a model and all its dependents
# File lib/torque/postgresql/inheritance.rb, line 27 def inheritance_merged_attributes @inheritance_merged_attributes ||= begin list = attribute_names list += casted_dependents.values.map(&:attribute_names) list.flatten.uniq.freeze end end
Check whether the model's table has directly or indirectly dependents
# File lib/torque/postgresql/inheritance.rb, line 72 def physically_inheritances? inheritance_dependents.present? end
Check if the model's table depends on any inheritance
# File lib/torque/postgresql/inheritance.rb, line 57 def physically_inherited? @physically_inherited ||= connection.schema_cache.dependencies( defined?(@table_name) ? @table_name : decorated_table_name, ).present? rescue ActiveRecord::ConnectionNotEstablished false end
Primary key is one exception when getting information about the class, it must returns the superclass PK
Raises an error message saying that the giver record class was not able to be casted since the model was not identified
# File lib/torque/postgresql/inheritance.rb, line 132 def raise_unable_to_cast(record_class_value) raise InheritanceError.new(<<~MSG.squish) An record was not able to be casted to type '#{record_class_value}'. If this table name doesn't represent a guessable model, please use 'Torque::PostgreSQL.conf.irregular_models = { '#{record_class_value}' => 'ModelName' }'. MSG end
Manually set the model name associated with tables name in order to facilitates the identification of inherited records
# File lib/torque/postgresql/inheritance.rb, line 86 def reset_table_name table = super adapter = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter if Torque::PostgreSQL.config.eager_load && connection.is_a?(adapter) connection.schema_cache.add_model_name(table, self) end table end
Private Instance Methods
Filter the record attributes to be loaded to not included those from another inherited dependent
# File lib/torque/postgresql/inheritance.rb, line 160 def filter_attributes_for_cast(record, klass) new_record = record.slice(*klass.attribute_names) table = new_record[_record_class_attribute.to_s] = klass.table_name # Recover aliased attributes (klass.attribute_names - inheritance_mergeable_attributes).each do |attribute| new_record[attribute] = record["#{table}__#{attribute}"] end # Add any additional columns and replace the record with the new record data new_record.merge!(record.slice(*(record.keys - inheritance_merged_attributes))) record.replace(new_record) end
# File lib/torque/postgresql/inheritance.rb, line 143 def instantiate_instance_of(klass, attributes, column_types = {}, &block) return super unless klass.physically_inheritances? auto_cast = _auto_cast_attribute.to_s record_class = _record_class_attribute.to_s return super unless attributes.key?(record_class) && attributes.delete(auto_cast) && attributes[record_class] != table_name klass = casted_dependents[attributes[record_class]] raise_unable_to_cast(attributes[record_class]) if klass.nil? filter_attributes_for_cast(attributes, klass) super(klass, attributes, column_types, &block) end