Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions lib/tapioca/dsl/compilers/active_record_associations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ class ActiveRecordAssociations < Compiler
class SourceReflectionError < StandardError
end

class SelfReferentialSourceReflectionError < StandardError
end

class MissingConstantError < StandardError
#: String
attr_reader :class_name
Expand Down Expand Up @@ -167,6 +170,10 @@ def populate_associations(mod)
add_error(<<~MSG.strip)
Cannot generate association `#{reflection.name}` on `#{constant}` since the source of the through association is missing.
MSG
rescue SelfReferentialSourceReflectionError
add_error(<<~MSG.strip)
Cannot generate association `#{reflection.name}` on `#{constant}` since the source of the through association is itself. Specify the `source:` option.
MSG
rescue MissingConstantError => error
add_error(<<~MSG.strip)
Cannot generate association `#{declaration(reflection)}` on `#{constant}` since the constant `#{error.class_name}` does not exist.
Expand Down Expand Up @@ -279,6 +286,8 @@ def validate_reflection!(reflection)
# and fails with a cryptic error, otherwise.
if reflection.through_reflection?
raise SourceReflectionError unless reflection.source_reflection
# A source reflection pointing back to itself makes `.klass` recurse forever
raise SelfReferentialSourceReflectionError if reflection.source_reflection.equal?(reflection)
end

# For non-polymorphic reflections, `.klass` should not be raising
Expand Down
16 changes: 16 additions & 0 deletions spec/tapioca/dsl/compilers/active_record_associations_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,22 @@ def shop_previously_changed?; end
Cannot generate association `manager` on `Post` since the source of the through association is missing.
MSG
end

it "generates RBI file for has_many :through association whose source is itself" do
add_ruby_file("group.rb", <<~RUBY)
class Group < ActiveRecord::Base
has_many :sub_groups, class_name: "Group", foreign_key: "parent_id"
has_many :child_group_members, through: :sub_groups
end
RUBY

refute_includes(rbi_for(:Group), "child_group_members")

assert_equal(1, generated_errors.size)
assert_equal(<<~MSG.strip, generated_errors.first)
Cannot generate association `child_group_members` on `Group` since the source of the through association is itself. Specify the `source:` option.
MSG
end
end
end

Expand Down
Loading