Skip to content

Commit

Permalink
fix: support has_many :through pointing at ActiveHash
Browse files Browse the repository at this point in the history
Closes #239
  • Loading branch information
flavorjones committed Dec 2, 2023
1 parent f1b792d commit 1ffe44a
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 4 deletions.
29 changes: 26 additions & 3 deletions lib/associations/associations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,35 @@ module ActiveHash
module Associations

module ActiveRecordExtensions

def self.extended(base)
require_relative 'reflection_extensions'
end

def has_many(association_id, **options)
if options[:through]
klass_name = association_id.to_s.classify
klass =
begin
klass_name.constantize
rescue StandardError, LoadError
nil
end

if klass && klass < ActiveHash::Base
define_method(association_id) do
join_models = send(options[:through])
join_models.flat_map do |join_model|
join_model.send(association_id.to_s.singularize)
end.uniq
end

return
end
end

super
end

def belongs_to(name, scope = nil, **options)
klass_name = options.key?(:class_name) ? options[:class_name] : name.to_s.camelize
klass =
Expand Down Expand Up @@ -117,6 +141,7 @@ def has_many(association_id, options = {})
klass.where(foreign_key => primary_key_value)
end
end

define_method("#{association_id.to_s.underscore.singularize}_ids") do
public_send(association_id).map(&:id)
end
Expand All @@ -140,7 +165,6 @@ def has_one(association_id, options = {})
end

def belongs_to(association_id, options = {})

options = {
:class_name => association_id.to_s.classify,
:foreign_key => association_id.to_s.foreign_key,
Expand All @@ -156,7 +180,6 @@ def belongs_to(association_id, options = {})
define_method("#{association_id}=") do |new_value|
attributes[options[:foreign_key].to_sym] = new_value ? new_value.send(options[:primary_key]) : nil
end

end
end

Expand Down
58 changes: 57 additions & 1 deletion spec/associations/active_record_extensions_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def define_school_classes
t.integer :locateable_id
t.integer :city_id
end

extend ActiveHash::Associations::ActiveRecordExtensions
end

Expand All @@ -58,6 +59,45 @@ def define_school_classes
define_ephemeral_class(:SchoolStatus, ActiveHash::Base)
end

def define_doctor_classes
define_ephemeral_class(:Physician, ActiveHash::Base) do
include ActiveHash::Associations

has_many :appointments
has_many :patients, through: :appointments

self.data = [
{:id => 1, :name => "ikeda"},
{:id => 2, :name => "sato"}
]
end

define_ephemeral_class(:Appointment, ActiveRecord::Base) do
establish_connection :adapter => "sqlite3", :database => ":memory:"
connection.create_table :appointments, force: true do |t|
t.references :physician
t.references :patient
end

extend ActiveHash::Associations::ActiveRecordExtensions

belongs_to :physician
belongs_to :patient
end

define_ephemeral_class(:Patient, ActiveRecord::Base) do
establish_connection :adapter => "sqlite3", :database => ":memory:"
connection.create_table :patients, force: true do |t|
end

extend ActiveHash::Associations::ActiveRecordExtensions

has_many :appointments
has_many :physicians, through: :appointments
end

end

before do
@ephemeral_classes = []
end
Expand Down Expand Up @@ -152,6 +192,23 @@ def define_school_classes
author.books.to_a
end
end

describe ":through" do
before { define_doctor_classes }

it "finds ActiveHash records through the join model" do
patient = Patient.create!

physician1 = Physician.first
Appointment.create!(physician: physician1, patient: patient)
Appointment.create!(physician: physician1, patient: patient)

physician2 = Physician.last
Appointment.create!(physician: physician2, patient: patient)

expect(patient.physicians).to contain_exactly(physician1, physician2)
end
end
end

describe ActiveHash::Associations::ActiveRecordExtensions do
Expand Down Expand Up @@ -332,6 +389,5 @@ def define_school_classes
end
end
end

end
end

0 comments on commit 1ffe44a

Please sign in to comment.