Searching full_name with ransack (first_name & last_name) #166

yigitbacakoglu opened this Issue Nov 19, 2012 · 15 comments


None yet

9 participants


How can i concat first_name and last_name to search with full name using ransack? @radar


jwg2s commented Nov 28, 2012

I'm also looking into doing this but have hit a bit of a brick wall. Does ransack support virtual attributes like this? Any help would be appreciated.

jwg2s commented Nov 28, 2012

That works for ransack purposes, but when the rest of the page loads, I get this error:

Cannot visit Arel::Nodes::InfixOperation

Might be missing something easy here.

ernie commented Nov 28, 2012

Without seeing your code, it's hard to say -- but you shouldn't be getting a cannot visit error for that node type. Unless, maybe, you're using an older version of ARel?

jwg2s commented Nov 28, 2012

In my model (user model):

ransacker :full_name do |parent|'||',
                            '||', parent.table[:first_name], ' '),

In my view:

<div class="control-group">
              <%= f.label :full_name_cont, 'Full Name' %>
              <%= f.text_field :full_name_cont, data: { autocomplete_source: Platform::User.order(:last_name).map(&:full_name)}, class: "span12 search-field search-query", placeholder: 'Full Name' %>

I'm not seeing any red flags here but I could be missing something or would more code be helpful?

ernie commented Nov 28, 2012

Can you drop the autocomplete stuff, just to narrow down the test case?

radar commented Nov 29, 2012

Which version of Ransack?

Please provide some steps or an example app to reproduce this issue.


In my model,

ransacker :lines do |parent|'||', parent.table[:line1], parent.table[:line2])


search ={"lines_cont" => "foo"})

when i type search.result.first, i receive Cannot visit Arel::Nodes::InfixOperation answer.

ransack version 0.7.0

(mysql database)


After restarting server, I realized that, if search cannot find correct result, it returns some wrong records.
For example, I search for lines_cont => 'foo' and there is no such record, search.result returns me a record which has 'bar' string in it.
Also if I type search.result.count during debugging, it raises Cannot visit Arel::Nodes::InfixOperation and I cannot make that lines search anymore until i restart server.

gudata commented Jan 18, 2013

with mysql it should be

  ransacker :full_name, :formatter => proc {|v| UnicodeUtils.downcase(v) } do |parent|'LOWER',
      ['concat_ws', [' ', parent.table[:first_name], parent.table[:middle_name], parent.table[:last_name]])]
tiekuhn commented Jul 3, 2013


I have a similar issue and came up with quite the same solution

ransacker :full_name do |parent|'concat_ws', [' ', parent.table[:first_name], parent.table[:last_name]])

while this code returns the correct results it has one major flaw --> the sql statement it produces is painfully slow as it is not using the index properly


searching for first name and lastname "separately" using AND as combinator --> returns in <1 sec
searching for the same records using the above ransacker code --> returns in ~ 53 sec

I already tried setting a combined index on the two columns --> wont help as we are using string concatenation.

Are you having any Idea how to

  • either speed up the query?
  • split the incoming "full_name" parameter into first_name and last_name and searching for these individually (combined with AND)?
gudata commented Jul 4, 2013

I guess that MySQL have to execute the concat_ws on every record so it couldn't be faster.


I was able to use with ransacker to sort on a "virtual attribute" (is that what they’re called in this context?), something like this (pseudo-code):

class Entry < ActiveRecord::Base


  ransacker :rank do |parent|'rank')

  def self.ranked
    select("DENSE_RANK() OVER (ORDER BY a DESC, b DESC, c DESC) AS rank")



Which allowed me to sort by the virtual attribute rank, e.g.:

q = { sorts: 'rank desc' }
assert_equal [3, 2, 1],

Not ideal that I'm using .map(&:rank) – I tried .pluck(:rank)but then the SELECT which calculates rank was being overridden.
And I suppose in this particular example, rank could just be cached to the db in a real column, so the virtual attribute would not be required.

So, I'd be happy to know of ways to improve this, but it does at least tie into ransack sort/filter nicely now.

jonatack commented Mar 9, 2014

If you need performance, I'd suggest using a dedicated, indexed search field as I describe in comments here and here toward the end of each conversation. Cheers :)

@jonatack jonatack closed this Mar 9, 2014

If anyone gets the following error:

Unsupported argument type: String. Construct an Arel node instead.

The solution is to build a quoted node:

  ransacker :full_name do |parent|'CONCAT_WS', [
      Arel::Nodes.build_quoted(' '), parent.table[:first_name], parent.table[:last_name]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment