2

The best way I've found to search for things where I specifically don't want character-case to matter is:

@tag = Rails.env.development? ? Category.where("LOWER(name) LIKE ?", "%#{params[:find]}%")[0] : Category.where("LOWER(name) ILIKE ?", "%#{params[:find]}%")[0]

I have to have the .env finder because I use Heroku, and I haven't cared to get PostgreSQL setup on my dev machines. Still, isn't there something like:

@tag = Category.find_by_name(params[:find], case_sensitive: false)

Are there options that we can pass to the find_by helper in Rails? This would be a nice one.

the Tin Man
  • 150,910
  • 39
  • 198
  • 279
Dudo
  • 3,511
  • 6
  • 28
  • 52
  • 1
    So, the next person to see this and think, 'F this guy, downvote,' please let me know why you think so. Thanks. – Dudo Oct 10 '13 at 19:26
  • 1
    I didn't downvote, but people are probably downvoting because you made a snide remark at the beginning that serves no purpose to your question... – Tyler Oct 10 '13 at 20:52
  • 1
    And which I removed because it was a non sequitur. – the Tin Man Oct 10 '13 at 23:16
  • Duly noted. But am I wrong? `case_sensitive:`, `order:`, `unique:`? Why not pass some options along to get more out of the `find_by` helper? – Dudo Oct 11 '13 at 04:06
  • well, we can do `.uniq` after it, so that's moot, but I'm sure people could come up with some good ones – Dudo Oct 11 '13 at 04:10

2 Answers2

14

Are there options that we can pass to the find_by helper in Rails? This would be a nice one...

No there isn't. (see the API)
Yes, that would be a nice one.

You will probably not accept this answer because your question wasn't really a question
Which is probably why you got downvoted.

Maybe you could also lowercase the params[:find] (params[:find].downcase) and care to get PG setup on your dev machines.

Category.where("LOWER(name) LIKE ?", "%#{params[:find].downcase}%").first

In the meantime, you could extract the query in your model:

category.rb

def self.search_by_name(name)
  if Rails.env.development?
    where("LOWER(name) LIKE ?", "%#{name.downcase}%").take
  else
    where("LOWER(name) ILIKE ?", "%#{name}%").take
  end       
end

controller

@tag = Category.search_by_name(params[:find])
Damien
  • 23,941
  • 7
  • 36
  • 39
  • Well, there was a question. You answered it... no, there isn't an options hash. You can do the `.downcase` if the info in the database is, too, lower case. I'm ok with downcasing everything, like I do with user emails when saved to the DB, but acronyms and initial-isms are definitely left upper case. For tagging, I thought that was important to leave alone. The PG is a non-issue, I was just explaining why I had the `Rails.env.development?` in there. – Dudo Oct 11 '13 at 03:26
  • So, an options hash for `find_by`. Any ideas on how we could implement that? I checked the source file in `activerecord-3.2.13/lib/active_record/dynamic_finder_match.rb`, and can verify, there are no options. It uses RegEx to interpret what you're looking for, but I'm not seeing the actual search functionality... – Dudo Oct 11 '13 at 04:06
  • I was meaning to lowercase both the search term **and** the db values: `Category.where("LOWER(name) ILIKE ?", "%#{params[:find].downcase}%")[0]`. I was thinking "Maybe you should also..." but wrote "Maybe you could also..." to make it sound more like a suggestion. – Damien Oct 11 '13 at 10:34
  • Also, I won't suggest you to implement that on your own because you will end up monkey patching rails. Just extract the query in your model for now and open an issue on Github to see if people are willing to implement that officially in Rails. – Damien Oct 11 '13 at 10:37
  • Lastly the dynamic finders will be deprecated. You should use anymore `find_by_name(name)` but `find_by(name: name)`. That is if you're using Rails 4, of course. – Damien Oct 11 '13 at 10:38
  • Oups, sorry, I was meaning to downcase the search term for the `LIKE` query, not the `ILIKE` – Damien Oct 11 '13 at 10:45
  • yeah, i read somewhere that the `find_by` helpers are 'slightly deprecated'. I don't see why... bleh. thanks for the insight, though, delba! – Dudo Oct 11 '13 at 17:17
  • It's deprecated because it uses metaprogramming techniques (method missigng) which requires to travel all the way up the methods chain. It is slow. – Damien Oct 11 '13 at 17:53
  • 2
    I disagree that you need to do this work. Use [Arel or Squeel](http://robb.weblaws.org/2013/12/05/yes-rails-supports-case-insensitive-database-queries/). Arel is built-in to Rails. – Dogweather Dec 06 '13 at 20:30
6

Yes, Rails supports case-insensitive queries via the built-in Arel library or a gem such as Squeel.

Dogweather
  • 12,603
  • 15
  • 54
  • 73