ransack_alias doesn't work in associations
class Parent
ransack_alias :full_name, :first_name_or_last_name
end
class Child
belongs_to :parent
end
Working scenario:
Parent.ransack(full_name_cont: 'a').result # works correctly
Error scenario:
Child.ransack(parent_full_name_cont: 'a').result
Result:
undefined method `type' for nil:NilClass (NoMethodError)
attr.klass.columns.find { |column| column.name == name }.type
^^^^^
This particular line of code is problematic for ActiveAdmin users, as well. If you use ActiveAdmin #includes on a has_one through, you will trigger a call to ransack. ActiveAdmin is feeding ransack the association through the parent, with the result that ransack is told to expect to find grandparent_id that does not exist. This line throws undefined method `type' for nil:NilClass.
Suppose class Whatever < ApplicationRecord has_one :grandparent, through: :parent. ActiveAdmin sends ransack instructions to look for whatevers.grandparent_id.
I can't help but feel there is inadequate error checking here in ransack. Further up the trace in
lib/ransack/nodes/condition.rb:25:in `extract'
there is this comment:
# TODO: Figure out what to do with multiple types of attributes,
# if anything. Tempted to go with "garbage in, garbage out" here.
Not being a ransack expert I can't say what the solution would be. But I can say this is a new error introduced since rack 3 and it seems improperly handled.
I'd like to point out that "mixed" compound conditions that contain an alias + an association do not work, too.
Consider the following setup:
class Author < ApplicationRecord
has_many :books, dependent: :destroy
def self.ransackable_attributes(auth_object = nil)
%w[full_name]
end
end
class Book < ApplicationRecord
ransack_alias :ttl, :full_title
belongs_to :author
def self.ransackable_associations(auth_object = nil)
%w[author]
end
def self.ransackable_attributes(auth_object = nil)
%w[full_title ttl]
end
end
Now, with this setup we have:
<%= search_form_for @q do |f| %>
<%# ✅ Case #1: alias for the model's attribute - works %>
<%= f.search_field :ttl_cont, placeholder: "Filter by full_title..." %>
<%# ✅ Case #2: association's attribute - works %>
<%= f.search_field :author_full_name_cont, placeholder: "Filter by author's name..." %>
<%# ✅ Case #3: model's attribute + association's attribute - works %>
<%= f.search_field :full_title_or_author_full_name_cont, placeholder: "Filter by author's name or title..." %>
<%# ❌ Case #4: alias + association - DOESN'T WORK! %>
<%# [NoMethodError] undefined method `type' for nil:NilClass %>
<%= f.search_field :ttl_or_author_full_name_cont, placeholder: "Filter by author's name or title..." %>
<%= f.submit "Search" %>
<% end %>