Skip to content

undefined method `polymorphic?' for ActiveRecord::Reflection::PolymorphicReflection #1039

@PhilCoggins

Description

@PhilCoggins

I am using Rails 5.2.3, and Ransack latest master(e17f1c6) and have found a potential bug.

It looks like this issue surfaces when trying to filter by a has_many through relationship where the source is a polymorphic belongs_to.

I am getting the below error:

undefined method `polymorphic?' for ActiveRecord::Reflection::PolymorphicReflection
# ./polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/reflection.rb:4:in `build_join_constraint'
     # /Users/philcoggins/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/bundler/gems/rails-5dbae010a9d4/activerecord/lib/active_record/associations/join_dependency/join_association.rb:33:in `block in join_constraints'
     # /Users/philcoggins/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/bundler/gems/rails-5dbae010a9d4/activerecord/lib/active_record/associations/join_dependency/join_association.rb:29:in `reverse_each'
     # /Users/philcoggins/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/bundler/gems/rails-5dbae010a9d4/activerecord/lib/active_record/associations/join_dependency/join_association.rb:29:in `with_index'
     # /Users/philcoggins/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/bundler/gems/rails-5dbae010a9d4/activerecord/lib/active_record/associations/join_dependency/join_association.rb:29:in `join_constraints'
     # ./polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb:53:in `make_constraints'
     # /Users/philcoggins/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/bundler/gems/rails-5dbae010a9d4/activerecord/lib/active_record/associations/join_dependency.rb:183:in `block in walk'
     # /Users/philcoggins/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/bundler/gems/rails-5dbae010a9d4/activerecord/lib/active_record/associations/join_dependency.rb:183:in `each'
     # /Users/philcoggins/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/bundler/gems/rails-5dbae010a9d4/activerecord/lib/active_record/associations/join_dependency.rb:183:in `flat_map'
     # /Users/philcoggins/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/bundler/gems/rails-5dbae010a9d4/activerecord/lib/active_record/associations/join_dependency.rb:183:in `walk'
     # ./polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb:41:in `block in join_constraints'
     # ./polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb:38:in `each'
     # ./polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb:38:in `flat_map'
     # ./polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb:38:in `join_constraints'
     # /Users/philcoggins/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/bundler/gems/rails-5dbae010a9d4/activerecord/lib/active_record/relation/query_methods.rb:1027:in `build_join_query'
     # /Users/philcoggins/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/bundler/gems/rails-5dbae010a9d4/activerecord/lib/active_record/relation/query_methods.rb:1009:in `build_joins'
     # /Users/philcoggins/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/bundler/gems/rails-5dbae010a9d4/activerecord/lib/active_record/relation/query_methods.rb:929:in `build_arel'
     # /Users/philcoggins/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/bundler/gems/rails-5dbae010a9d4/activerecord/lib/active_record/relation/query_methods.rb:903:in `arel'
     # /Users/philcoggins/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/bundler/gems/rails-5dbae010a9d4/activerecord/lib/active_record/relation.rb:454:in `block in to_sql'
     # /Users/philcoggins/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/bundler/gems/rails-5dbae010a9d4/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:206:in `unprepared_statement'
     # /Users/philcoggins/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/bundler/gems/rails-5dbae010a9d4/activerecord/lib/active_record/relation.rb:454:in `to_sql'
     # ./spec/ransack/search_spec.rb:295:in `block (3 levels) in <module:Ransack>'

I have forked your repository and produced a failing test case in a separate branch here. I had to nudge the models a bit to get my test case to work, but it does closely resemble a relationship that I have in my production application.

I have monkey-patched with the below, but I'm really not sure if this is what it's supposed to be (everything seems to be working great so far):

# overrides lib/polyamorous/activerecord_5.2.0_ruby_2/reflection.rb
module Polyamorous
  module ReflectionExtensions
    def build_join_constraint(table, foreign_table)
      if respond_to?(:polymorphic?) && polymorphic?
        super(table, foreign_table)
        .and(foreign_table[foreign_type].eq(klass.name))
      elsif @reflection.is_a?(ActiveRecord::Reflection::PolymorphicReflection)
        super(table, foreign_table)
        .and(foreign_table[@reflection.foreign_type].eq(klass.name))
      else
        super(table, foreign_table)
      end
    end
  end
end

Any assistance would be great, happy to work up a PR if someone can provide a nudge in the right direction.

Thanks for your time!

EDIT
I found an issue with the above monkey patch that was causing some queries with polymorphic joins to not add a filter on the polymorphic type. I have updated the original code in this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions