diff --git a/demo_functionality.rb b/demo_functionality.rb index 4bca778..6d157df 100755 --- a/demo_functionality.rb +++ b/demo_functionality.rb @@ -41,6 +41,7 @@ ActiveRecord::Schema.define do to_table: :users_fa_aux, primary_key: :base_table_id } + t.integer :category t.integer :fa_id, index: true t.string :title t.string :species @@ -99,6 +100,7 @@ class FaPost < Post belongs_to :creator, class_name: "FaUser", inverse_of: :created_posts validates :fa_id, presence: true, uniqueness: true validates :title, presence: true + enum :category, { image: 0, video: 1, text: 2 } end class E621Post < Post diff --git a/lib/has_aux_table.rb b/lib/has_aux_table.rb index 8dfc956..920695d 100644 --- a/lib/has_aux_table.rb +++ b/lib/has_aux_table.rb @@ -57,6 +57,7 @@ module HasAuxTable setup_attributes_hook!(config) setup_relation_extensions!(config) setup_attribute_getter_setter_hooks!(config) + setup_enum_hook!(config) config end @@ -198,9 +199,8 @@ module HasAuxTable sig { params(load_schema_method: Method, config: AuxTableConfig).void } def aux_config_load_schema!(load_schema_method, config) # first, load the main and aux table schemas like normal - result = load_schema_method.call config.load_aux_schema - + result = load_schema_method.call aux_table_name = config.aux_table_name check_for_overlapping_columns!( @@ -356,6 +356,49 @@ module HasAuxTable "Auxiliary table columns must not overlap with main table columns." end end + + sig { params(config: AuxTableConfig).void } + def setup_enum_hook!(config) + self.define_singleton_method( + :enum + ) do |name = nil, values = nil, **options, &block| + name = name.to_s + config.aux.klass.enum(name, values, **options, &block) + self.defined_enums.merge!(config.aux.klass.defined_enums) + + # define methods on the main class that delegate to the aux class + config + .aux + .klass + .send(:_enum_methods_module) + .instance_methods + .each do |method_name| + self + ._enum_methods_module + .define_method(method_name) do |*args, **kwargs, &block| + raise "not implemented" + end + end + + define_singleton_method(name.pluralize) do + config.aux.klass.send(name.pluralize) + end + + values.keys.each do |value_name| + value_name = [options[:prefix], value_name, options[:suffix]].reject( + &:blank? + ).join("_") + [ + value_name, + "#{value_name}?", + "#{value_name}!", + "#{value_name}=" + ].each do |method_name| + config.define_aux_attribute_delegate(method_name.to_sym) + end + end + end + end end mixes_in_class_methods(ClassMethods) end diff --git a/lib/has_aux_table/aux_table_config.rb b/lib/has_aux_table/aux_table_config.rb index 7879643..8c5c097 100644 --- a/lib/has_aux_table/aux_table_config.rb +++ b/lib/has_aux_table/aux_table_config.rb @@ -121,7 +121,7 @@ module HasAuxTable const :foreign_key, KeyType const :primary_key, KeyType - sig { void } + sig { returns(T.untyped) } def load_aux_schema aux_class.load_schema end diff --git a/spec/active_record/has_aux_table_spec.rb b/spec/active_record/has_aux_table_spec.rb index 17db2ef..a7ae1bf 100644 --- a/spec/active_record/has_aux_table_spec.rb +++ b/spec/active_record/has_aux_table_spec.rb @@ -111,6 +111,31 @@ RSpec.describe HasAuxTable do expect(driver.car).to eq(car) end + it "defined_enums returns the correct values" do + engine_types = { + "turbofan" => 0, + "turboprop" => 1, + "piston" => 2, + "electric" => 3 + } + expect(Plane.defined_enums).to eq({ "engine_type" => engine_types }) + expect(Plane.engine_types).to eq(engine_types) + end + + it "works with enums" do + plane = Plane.create!(name: "Boeing 747", engine_type: :turbofan) + expect(plane.engine_type).to eq("turbofan") + + plane.engine_type = "piston" + expect(plane.engine_type).to eq("piston") + plane.save! + expect(plane.engine_type).to eq("piston") + expect(plane.piston?).to be_truthy + + plane.turboprop! + expect(plane.engine_type).to eq("turboprop") + end + describe "#changed?" do it "returns true if the main record changes" do car = Car.create!(name: "Honda Civic") diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e00bc0c..62913c5 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -81,6 +81,10 @@ module SpecHelper t.create_aux :boat do |t| t.boolean :only_freshwater end + + t.create_aux :plane do |t| + t.integer :engine_type + end end create_base_table :people do |t| diff --git a/spec/spec_models.rb b/spec/spec_models.rb index 3bc7dfd..68ebef5 100644 --- a/spec/spec_models.rb +++ b/spec/spec_models.rb @@ -21,6 +21,11 @@ class Boat < Vehicle belongs_to :captain, inverse_of: :boat end +class Plane < Vehicle + aux_table :plane + enum :engine_type, { turbofan: 0, turboprop: 1, piston: 2, electric: 3 } +end + class Person < ActiveRecord::Base include HasAuxTable self.table_name = "people"