Skip to content

Commit

Permalink
Raise error when passing passing a class to :source_type
Browse files Browse the repository at this point in the history
Raise `ArgumentError` when `:source_type` is given as class
in `has_many :through` relation.

Closes #41092
  • Loading branch information
intrip authored and dhh committed Jan 28, 2021
1 parent eb51999 commit ff0f158
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 3 deletions.
12 changes: 9 additions & 3 deletions activerecord/lib/active_record/reflection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,12 @@ def predicate_builder(table)
def primary_key(klass)
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
end

def ensure_option_not_given_as_class!(option_name)
if options[option_name] && options[option_name].class == Class
raise ArgumentError, "A class was passed to `:#{option_name}` but we are expecting a string."
end
end
end

# Base class for AggregateReflection and AssociationReflection. Objects of
Expand Down Expand Up @@ -426,9 +432,7 @@ def initialize(name, scope, options, active_record)
@type = -(options[:foreign_type]&.to_s || "#{options[:as]}_type") if options[:as]
@foreign_type = -(options[:foreign_type]&.to_s || "#{name}_type") if options[:polymorphic]

if options[:class_name] && options[:class_name].class == Class
raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
end
ensure_option_not_given_as_class!(:class_name)
end

def association_scope_cache(klass, owner, &block)
Expand Down Expand Up @@ -748,6 +752,8 @@ def initialize(delegate_reflection)
@delegate_reflection = delegate_reflection
@klass = delegate_reflection.options[:anonymous_class]
@source_reflection_name = delegate_reflection.options[:source]

ensure_option_not_given_as_class!(:source_type)
end

def through_reflection?
Expand Down
7 changes: 7 additions & 0 deletions activerecord/test/cases/reflection_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,13 @@ def test_class_for_class_name
assert_equal "A class was passed to `:class_name` but we are expecting a string.", error.message
end

def test_class_for_source_type
error = assert_raises(ArgumentError) do
ActiveRecord::Reflection.create(:has_many, :tagged_posts, nil, { through: :taggings, source: :taggable, source_type: Post }, Tag)
end
assert_equal "A class was passed to `:source_type` but we are expecting a string.", error.message
end

def test_join_table
category = Struct.new(:table_name, :pluralize_table_names).new("categories", true)
product = Struct.new(:table_name, :pluralize_table_names).new("products", true)
Expand Down

0 comments on commit ff0f158

Please sign in to comment.