id column rewriting

This commit is contained in:
Dylan Knutson
2025-07-29 16:18:37 +00:00
parent 94c2fb9593
commit 3016a17480
6 changed files with 207 additions and 101 deletions

View File

@@ -166,6 +166,7 @@ module HasAuxTable
next
end
else
# TODO - add support for ActiveRecord::Reflection::ThroughReflection
raise "unsupported association type: #{assoc.class}"
end
end

View File

@@ -13,12 +13,12 @@ module HasAuxTable
column_names.include?(name.to_s)
end
sig { params(name: String).returns(T::Boolean) }
sig { params(name: T.any(String, Symbol)).returns(T::Boolean) }
def is_primary_key?(name)
primary_keys.include?(name.to_sym)
end
sig { params(name: String).returns(T::Boolean) }
sig { params(name: T.any(String, Symbol)).returns(T::Boolean) }
def is_type_key?(name)
type_key == name.to_s
end

View File

@@ -51,18 +51,24 @@ class ActiveRecord::Associations::AssociationScope
klass = refl.klass
next unless klass.is_a?(HasAuxTable::ClassMethods)
next unless aux_config = klass.aux_table_for(refl.join_primary_key)
aux_table = aux_config.aux.klass.table_name
main_table = aux_config.main.klass.table_name
aux_table =
scope.connection.quote_table_name(aux_config.aux.klass.table_name)
main_table =
scope.connection.quote_table_name(aux_config.main.klass.table_name)
main_keys =
aux_config.main.primary_keys.map { |key| "'#{main_table}'.'#{key}'" }
aux_config.main.primary_keys.map do |key|
"#{main_table}.#{scope.connection.quote_column_name(key)}"
end
aux_keys =
aux_config.aux.primary_keys.map { |key| "'#{aux_table}'.'#{key}'" }
aux_config.aux.primary_keys.map do |key|
"#{aux_table}.#{scope.connection.quote_column_name(key)}"
end
join_clause =
main_keys
.zip(aux_keys)
.map { |(main_key, aux_key)| "#{main_key} = #{aux_key}" }
.join(" AND ")
scope.joins!("INNER JOIN '#{main_table}' ON (#{join_clause})")
scope.joins!("INNER JOIN #{main_table} ON (#{join_clause})")
end if association.is_a?(
ActiveRecord::Associations::HasManyThroughAssociation
)
@@ -122,7 +128,26 @@ module HasAuxTable
relation_class.send(:define_method, :pluck) do |*column_names|
T.bind(self, ActiveRecord::Relation)
if (predicates = Util.try_relation_optimization(self, aux_config))
aux_relation = aux_config.aux.klass.where(predicates)
aux_relation = aux_config.aux.klass.all
column_names.map! do |column_name|
if aux_config.main.is_primary_key?(column_name)
aux_table_name =
self.connection.quote_table_name(
aux_config.aux.klass.table_name
)
pkey_column_name =
self.connection.quote_column_name(
aux_config.aux.klass.primary_key
)
column_name = self.connection.quote_column_name(column_name)
Arel.sql(
"#{aux_table_name}.#{pkey_column_name} AS #{column_name}"
)
else
column_name
end
end
aux_relation.where!(predicates) if predicates.any?
aux_relation.pluck(*column_names)
else
pluck_method.bind(self).call(*column_names)
@@ -133,10 +158,15 @@ module HasAuxTable
relation_class.send(
:define_method,
:calculate
) do |operation, column_name|
) do |operation, column_name = nil|
T.bind(self, ActiveRecord::Relation)
if (predicates = Util.try_relation_optimization(self, aux_config))
aux_relation = aux_config.aux.klass.where(predicates)
aux_relation = aux_config.aux.klass.all
if column_name && aux_config.main.is_primary_key?(column_name)
column_name = aux_config.aux.klass.primary_key
end
aux_relation.where!(predicates) if predicates.any?
aux_relation.calculate(operation, column_name)
else
calculate_method.bind(self).call(operation, column_name)