Ruby on Rails find_by case insensitive - sql

I need to find a record from 2 parameters but I need one of them to be case insensitive. The current case sensitive line is
c = Course.find_by(subject_area: area, cat_number: cat)
But I need subject_area to be case insensitive. How would I achieve that?

It depends on the database, and you may need to pass in db-specific SQL for that (and not use find_by).
Are you using postrges? if so, this would normally work:
Course.where("LOWER(subject_area) = ? AND cat_number = ?", area.downcase, cat)
alternatively you could convert your subject_area to downcase every time you save a new one... then just use:
Course.find_by(subject_area: area.downcase, cat_number: cat)
I could be wrong, but don't currently know of any rails-native way of doing a case insensitive rails find_by

An alternative can be
c = Course.find_by("LOWER(subject_area)= ? AND cat_number = ?", area.downcase, cat)

If you are using postgres, you could do something like:
> c = Course.find_by('subject_area ILIKE ? AND cat_number LIKE ?', area, cat)
(ILIKE is used to do insensitive search)

If you need to have this attribute be case-insensitive then the right way is to ensure it's always one particular in your model
before_save { self.subject_area = subject_area.downcase }
You can migrate your existing data to be downcased as well.
Having done that your find by operation still needs to ensure that the area is downcased in query as suggested.
Course.find_by(subject_area: area.downcase, cat_number: cat)
Option 2:
I knew I was forgetting this. Let's say you dont want to go migration path. Just define a scope.
http://guides.rubyonrails.org/v4.1/active_record_querying.html#scopes
scope :area_nocase, (area) -> { where("LOWER(subject_area) = ?", area.downcase) }
then you can use it like
Course.area_nocase(area) or cat.course.area_nocase(area)
or chain it however you need to.

Related

ActiveRecord outputs too much in select query for Rails

According to:
#actors = actors.to_sql
this query:
actors = Actor.select("actors.name")
supposed to be equal to:
SELECT actors.name FROM `actors`
And it works in my SQL; only selects actors.name ... so i try:
#actors = actors.to_json.to_s
and render on some view... I get this;
[{"name":"James Patrick Pe","id":null,"logo":{"url":"uploads/default.jpg","topbar_avatar":{"url":"uploads/topbar_avatar_default.jpg"}}},{"name":"SSS","id":null,"logo":{"url":"uploads/default.jpg","topbar_avatar":{"url":"uploads/topbar_avatar_default.jpg"}}},{"name":"Philhealth","id":nul ....
it's basically a JSON of everything... I only need one column for an AJAX reply. How can I do this with the ActiveRecord Way?
Do you use Paperclip? It's likely you have a method that appends something to your JSON.
What you need to do is to specify the fields you want to be exported.
#actors = actors.to_json(only: [:name]).to_s
Also please note that there is a better approach to to_json. You should definitely have serializers that take an object or collection in input and deal with the serialization.

ArangoDB AQL Non Case Sensitive Comparison

Let's imagine I have a few simple docs stored in an Arango collection like so:
[
{"type":Cat, "quality":Fuzzy}
{"type":Dog, "quality":Barks}
{"type":Rabbit, "quality":Hoppy}
{"type":Pig, "quality":Chubby}
{"type":Red Panda, "quality":Fuzzy}
{"type":Monkey, "quality":Hairy}
]
Now let's say a user initiates a search in my application for all animals that are 'fuzzy', all lower case. Is there a way with AQL to make a comparison that is not case sensitive? So for instance:
FOR a IN animals
FILTER a.type.toLowerCase() == fuzzy
RETURN a
Now I know the above example doesn't work, but it would be nice if there was a way to do this. Thanks!
There is a LOWER string function in AQL which you can try to use in your query like this:
FOR a IN animals
FILTER LOWER(a.quality) == 'fuzzy'
RETURN a

SQL Syntax and Rails: how to generate list of db records with trailing whitespace in console

I'm in the Rails console and I want to generate a list of user names that have a trailing whitespace in them. I was thinking that the syntax would look like this, but it didn't work. Any change a better programmer than me can point out what I'm doing wrong?
> User.name.where("% ")
Don't know if you're using MySQL, but an approach would be:
User.where("name LIKE '% '")
You may change this according to your database. This is kinda slow, though.
One way is
Job.all.select{|j| j =~ /^\d+$/}
but it may not be as efficient as the MySQL version.
Another possibility is to use a named scope to hide the ugly SQL:
named_scope :all_digits, lambda { |regex_str|
{ :condition => [" invoice_number REGEXP '?' " , regex_str] }
}
Then you have Job.all_digits.
Answer taken from How to specify Ruby regex when using Active Record in Rails?
You can have
regex_str = "\w+\s+$"
Thanks
Here's what I went with:
User.all.select { |c| c.name.end_with?(" ") }
This got me the list I needed.
It's based on Paritosh's first answer. I'm making his a the canonical answer because I think it's a better resource in general. My solution only helps me, but his has a lot of strategies that would be helpful.

Rails: How to find_by a field containing a certain string

I have a model named Topic, that has a name as a field.
So say I have a term I'm searching for, apple.
If I do a
Topic.find_by_name("apple")
I get a record back with the name apple. That's good -- but how do I change find_by_name so that it can find "apple juice" as well as "apple" -- basically, find names that contain the original query or exactly match the original query?
Edit:
Thanks for all the response. I guess I should've been a little more clear earlier, but what if I want to find by a variable name (obviously I'm not going to want to find by the name "apple" everytime :) )?
How do I manipulate Topic.where to accommodate for this?
So something like...
#topic = Topic.where(......., #name)
I think something like this should work:
Topic.where("name like ?", "%apple%")
To accomodate for your edit:
Topic.where("name like ?", "%#{#search}%")
Basic string interpolation, you're using the value of #search inside the string %%, so you #search = "apple" then you end up with %apple%
With PostgreSQL you can also use match operators:
Topic.where("name ~* ?", #search)
Looks like in Rails 3 you would want to use the where:
Topic.where("name ILIKE ?", "%apple%")
Don't put string directly like that. Its called SQL injection. You should instead use .where:
Topic.where("name like '?%' ", params[:name])
Try
Topic.where("name like ?",'%apple%')
Topic.find(:all, :conditions => ["name like ?","%apple%"])

Rails3 - Is there a way to do NOTLIKE?

I previously asked a question regarding pulling specific items out of a database if they contained a specific word in their string, someone kindly offered the following which did just the job:
def SomeModel < ActiveRecord::Base
scope :contains_city,
lambda { |city| where("some_models.address LIKE ?","%"+city+"%" ) }
end
However, I have some instances where I would like to do the opposite, i.e. pull out all the items which do not have the specified word in their string. Is there a way to do a NOT LIKE function? I have prevously seen people use '!=' for a NOT EQUALS, but have had no success along these lines for the LIKE function. Is there an equivalent or is it best to iterate through the database putting items in 2 separate databases based on whether they satisfy the LIKE condition?
You could try NOT LIKE in your query; MySQL supports this.
http://dev.mysql.com/doc/refman/5.0/en/string-comparison-functions.html