Using Ransack with last child record search

151 Views Asked by At

I have a parent with many children. I am interested in searching a column on the last (highest ID) child record.

I have seen a reference to a "_last" association syntax in Ransack, and it is exactly what I want to do. But it doesn't work and I can find no reference to it in the docs. It would look like this:

Parent.ransack(children_last_name_eq: "search term").result

This should search the name column of the last child of the parent and return the parent records that match. This would be ideal, but doesn't work.

So I created a scoped has_one association like:

class Parent
  has_many :children
  has_one :last_child, -> { order(id: :desc) }, class_name: "Child"
end

Now parent.last_child correctly returns the last child object. Then I created a Ransack query using this:

Parent.ransack(last_child_name_eq: "search term").result

This runs, but when I look at the SQL it generates, it drops the scoping to the last child record, and searches on all the child records. I assume when ransack builds the SQL, it interprets the has_one differently than active record does.

My actual ransack query is vastly more complicated than this, so I can't implement anything that would break other search params. Ransack 2.3.2 on Rails 5.2 using MySQL 5.7

1

There are 1 best solutions below

0
ikinner On

I got this working using a default scope in the model and a custom ransack line:

default_scope {
  joins('JOIN children ON parent.id = children.parent_id and children.id = (SELECT MAX(children.id) FROM children WHERE children.parent_id = parent.id)')
}

ransacker :child_name, type: :string do
  Arel.sql('children.name')
end