Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ransack not_eq not working #925

Open
msyesyan opened this issue Jun 14, 2018 · 9 comments · May be fixed by #1279
Open

Ransack not_eq not working #925

msyesyan opened this issue Jun 14, 2018 · 9 comments · May be fixed by #1279

Comments

@msyesyan
Copy link

msyesyan commented Jun 14, 2018

undefined method eq for #<Arel::Nodes::Equality:0x007fb12685a2d0>

I found there is a closed issue about this issue. And I have found the repro steps. The issues occurs when ransack a association attributes and the child model extend a parent model.

for example:

class Patient
    has_many :visits
    has_many :follow_visits
end

class Visit
    belongs_to :patient
end

class FollowVisit < Visit
    belongs_to :patient
end
Patient.ransack({visits_name_not_eql: 'test'}) #=> this is successful
Patient.ransack({follow_visits_name_not_eql: 'test'}) #=> raise this error

I have followed the source code, and I found the error code is in adapters/active_record/context.rb:193

def build_correlated_subquery(association)
  join_constraints = extract_joins(association)
  join_root = join_constraints.shift
  correlated_key = join_root.right.expr.left
  subquery = Arel::SelectManager.new(association.base_klass)
  subquery.from(join_root.left)
  subquery.project(correlated_key)
  join_constraints.each do |j|
    subquery.join_sources << Arel::Nodes::InnerJoin.new(j.left, j.right)
  end
  binding.pry
  subquery.where(correlated_key.eq(primary_key))
end

the expect(correlated_key.is_a? Ransack::Nodes::Attribute).to be_true is false, because correlated_key is a Arel::Nodes::Equality
I don't know how to fix this, can you help ? @seanfcarroll thanks

@msyesyan
Copy link
Author

msyesyan commented Jun 21, 2018

I haven't find a good way to fix this, @jonatack could you please have a look? ^_^

@alexisraca
Copy link

Try declaring the table name in the STI model. @msyesyan

@ciihla
Copy link

ciihla commented Dec 1, 2021

I think I found the issue, not sure, but if I change in the Context#extract_correlated_key to detect children its working..

when Arel::Nodes::And
if join_root.children.any?
join_root.children.each do |child|
eck = extract_correlated_key(child)
return eck unless eck.nil?
end
else
extract_correlated_key(join_root.left) || extract_correlated_key(join_root.right)
end

@deivid-rodriguez
Copy link
Contributor

@ciihla Can you create a PR with your solution?

@ciihla
Copy link

ciihla commented Mar 8, 2022

I don't have time for writing proper tests, etc, but basically, this is working for us:

module RansackPatch
  def self.included(base)
    base.class_eval do
      alias_method :extract_correlated_key, :extract_correlated_key_with_children_support
    end
  end

  def extract_correlated_key_with_children_support(join_root)
    case join_root
    when Arel::Nodes::OuterJoin
      # one of join_root.right/join_root.left is expected to be Arel::Nodes::On
      if join_root.right.is_a?(Arel::Nodes::On)
        extract_correlated_key(join_root.right.expr)
      elsif join_root.left.is_a?(Arel::Nodes::On)
        extract_correlated_key(join_root.left.expr)
      else
        raise 'Ransack encountered an unexpected arel structure'
      end
    when Arel::Nodes::Equality
      pk = primary_key
      if join_root.left == pk
        join_root.right
      elsif join_root.right == pk
        join_root.left
      end
    when Arel::Nodes::And
      # This is new to support nested children
      if join_root.children.any?
        join_root.children.each do |child|
          eck = extract_correlated_key(child)
          return eck unless eck.nil?
        end
      else
        extract_correlated_key(join_root.left) || extract_correlated_key(join_root.right)
      end
    else # rubocop:disable Style/EmptyElse
      # eg parent was Arel::Nodes::And and the evaluated side was one of
      # Arel::Nodes::Grouping or MultiTenant::TenantEnforcementClause
      nil
    end
  end
end

::Ransack::Adapters::ActiveRecord::Context.include RansackPatch

@deivid-rodriguez
Copy link
Contributor

It'd be ok to just create a PR with the patch, I can handle tests later.

@ciihla
Copy link

ciihla commented Mar 8, 2022

@deivid-rodriguez
Copy link
Contributor

Thanks!

@deivid-rodriguez deivid-rodriguez linked a pull request Mar 8, 2022 that will close this issue
@deivid-rodriguez
Copy link
Contributor

I tried to reproduce this with a spec using the models in the original post, but it all worked fine (I had to modify the models to actually inherit from ActiveRecord::Base). So still struggling to find a repro here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants