Skip to content

Commit

Permalink
Fix STI support for subclasses
Browse files Browse the repository at this point in the history
- Rails 7.0 deprecated the `direct_descendants` method in favor of `subclasses`
- Ruby 3.1 added native `subclasses` support to `Class`

Ref #179

Ref:
- Alias direct_descendants as subclasses: rails/rails@8f8aa85 rails/rails#39505
- Filter reloaded classes in Class#subclasses and Class#descendants core exts: rails/rails@1aa2463 rails/rails#46144
  • Loading branch information
tagliala committed Oct 8, 2022
1 parent 83493f6 commit 081e79a
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 11 deletions.
31 changes: 27 additions & 4 deletions lib/chrono_model/time_machine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,35 @@ module TimeMachine
ChronoModel.history_models[table_name] = history

class << self
alias_method :direct_descendants_with_history, :direct_descendants
def direct_descendants
direct_descendants_with_history.reject(&:history?)
if Rails.version >= '7.0'
alias_method :subclasses_with_history, :subclasses
def subclasses
subclasses_with_history.reject(&:history?)
end

# `direct_descendants` is deprecated method in 7.0 and has been
# removed in 7.1
if method_defined?(:direct_descendants)
alias_method :direct_descendants_with_history, :subclasses_with_history
alias_method :direct_descendants, :subclasses
end

# Ruby 3.1 has a native subclasses method and descendants is
# implemented with recursion of subclasses
if Class.method_defined?(:subclasses)
def descendants_with_history
subclasses_with_history.concat(subclasses.flat_map(&:descendants))
end
end
else
alias_method :descendants_with_history, :descendants

alias_method :direct_descendants_with_history, :direct_descendants
def direct_descendants
direct_descendants_with_history.reject(&:history?)
end
end

alias_method :descendants_with_history, :descendants
def descendants
descendants_with_history.reject(&:history?)
end
Expand Down
43 changes: 36 additions & 7 deletions spec/chrono_model/time_machine/sti_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,50 @@ class ::Element < ActiveRecord::Base
include ChronoModel::TimeMachine
end

class ::Publication < Element
class ::Publication < ::Element
end

class ::Magazine < ::Publication
end

describe '.descendants' do
subject { Element.descendants }
subject { Element.descendants.map(&:name) }

it { is_expected.to_not include(Element::History) }
it { is_expected.to include(Publication) }
it { is_expected.to match_array %w[Publication Magazine] }
end

describe '.descendants_with_history' do
subject { Element.descendants_with_history }
subject { Element.descendants_with_history.map(&:name) }

it { is_expected.to match_array %w[Element::History Publication Magazine] }
end

if Element.respond_to?(:direct_descendants)
describe '.direct_descendants' do
subject { Element.direct_descendants.map(&:name) }

it { is_expected.to match_array %w[Publication] }
end

describe '.direct_descendants_with_history' do
subject { Element.direct_descendants_with_history.map(&:name) }

it { is_expected.to include(Element::History) }
it { is_expected.to include(Publication) }
it { is_expected.to match_array %w[Element::History Publication] }
end
end

if Element.respond_to?(:subclasses)
describe '.subclasses' do
subject { Element.subclasses.map(&:name) }

it { is_expected.to match_array %w[Publication] }
end

describe '.subclasses_with_history' do
subject { Element.subclasses_with_history.map(&:name) }

it { is_expected.to match_array %w[Element::History Publication] }
end
end

describe 'timeline' do
Expand Down

0 comments on commit 081e79a

Please sign in to comment.