update tapioca, more type annotations

This commit is contained in:
Dylan Knutson
2025-07-16 16:24:35 +00:00
parent fda95fb33f
commit 19d96dfebe
37 changed files with 107366 additions and 6123 deletions

View File

@@ -8,6 +8,7 @@ require "active_support"
require "active_support/concern"
require "active_model/attribute_set"
require_relative "has_aux_table/key_type"
require_relative "has_aux_table/util"
require_relative "has_aux_table/relation_extensions"
require_relative "has_aux_table/aux_table_config"
@@ -22,6 +23,7 @@ module HasAuxTable
module ClassMethods
extend T::Sig
extend T::Helpers
include RelationExtensions
# Main DSL method for defining auxiliary tables
@@ -231,8 +233,19 @@ module HasAuxTable
end
# Generate auxiliary model class dynamically
sig { params(table_name: Symbol).returns(AuxTableConfig) }
def generate_aux_config(table_name)
sig do
params(
table_name: Symbol,
foreign_key: KeyType,
primary_key: KeyType
).returns(AuxTableConfig)
end
def generate_aux_config(
table_name,
# The column on the aux table that points to the main table
foreign_key: :base_table_id,
primary_key: self.primary_key
)
# Generate class name (e.g., :car_aux => "CarAux")
aux_class_name = table_name.to_s.camelize
aux_association_name = table_name.to_s.singularize.to_sym
@@ -242,19 +255,13 @@ module HasAuxTable
Kernel.raise ArgumentError, "Class #{aux_class_name} already exists"
end
# Get the base class name for the foreign key (e.g., Vehicle -> vehicle_id)
# In STI, all subclasses share the same table, so we need the base class
foreign_key = :base_table_id
# Get the current class for the association
main_class = self
main_association_name = main_class.name.underscore.to_sym
primary_key = :id
# Create the auxiliary model class
aux_class =
Class.new(ActiveRecord::Base) do
# Set the table name
self.table_name = table_name.to_s
self.primary_key = foreign_key

View File

@@ -1,4 +1,4 @@
# typed: false
# typed: strict
# frozen_string_literal: true
module HasAuxTable
@@ -10,8 +10,8 @@ module HasAuxTable
const :main_association_name, Symbol
const :main_class, T.class_of(ActiveRecord::Base)
const :model_class, T.class_of(ActiveRecord::Base)
const :foreign_key, T.any(Symbol, T::Array[Symbol])
const :primary_key, T.any(Symbol, T::Array[Symbol])
const :foreign_key, KeyType
const :primary_key, KeyType
sig { void }
def load_aux_schema
@@ -25,9 +25,15 @@ module HasAuxTable
end
sig do
params(name: Symbol, value: T.untyped, block: T.proc.void).returns(
Arel::Nodes::Node
)
params(
name: Symbol,
value: T.untyped,
block:
T
.proc
.params(arel_attr: T.untyped, aux_bind: T.untyped)
.returns(Arel::Nodes::Node)
).returns(Arel::Nodes::Node)
end
def aux_bind_attribute(name, value, &block)
arel_attr = model_class.arel_table[name]
@@ -48,8 +54,9 @@ module HasAuxTable
def define_aux_attribute_delegate(main_class, method_name)
aux_config = self
main_class.define_method(method_name) do |*args, **kwargs|
T.bind(self, ActiveRecord::Base)
aux_model = aux_config.ensure_aux_target(self)
aux_model.public_send(method_name, *args, **kwargs)
T.unsafe(aux_model).public_send(method_name, *args, **kwargs)
end
end
@@ -94,19 +101,22 @@ module HasAuxTable
sig { returns(T::Array[String]) }
def aux_column_names
@aux_column_names ||=
begin
rejected_columns = [
self.foreign_key,
self.primary_key,
"created_at",
"updated_at"
].flatten.map(&:to_s)
T.let(
begin
rejected_columns = [
self.foreign_key,
self.primary_key,
"created_at",
"updated_at"
].flatten.map(&:to_s)
model_class
.column_names
.reject { |col| rejected_columns.include?(col.to_s) }
.map(&:to_s)
end
model_class
.column_names
.reject { |col| rejected_columns.include?(col.to_s) }
.map(&:to_s)
end,
T.nilable(T::Array[String])
)
end
sig { params(name: T.any(Symbol, String)).returns(T::Boolean) }
@@ -122,7 +132,8 @@ module HasAuxTable
)
end
def partition_by_aux_columns(hash)
hash.partition { |k, _| !self.is_aux_column?(k) }.map(&:to_h)
a, b, _ = hash.partition { |k, _| !self.is_aux_column?(k) }.map(&:to_h)
[T.must(a), T.must(b)]
end
end
end

View File

@@ -0,0 +1,9 @@
# typed: strict
# frozen_string_literal: true
module HasAuxTable
KeyType =
T.type_alias do
T.any(T.any(Symbol, String), T::Array[T.any(Symbol, String)])
end
end