Using Like in Rails SQL - ruby-on-rails

I got a little problem using the LIKE sentence on rails i know that this next sentence works:
Brand.find(:all, :joins=>[:cars], :conditions=>["brandname LIKE ?","%ford%"])
But it's any way around that I could to something like this:
Brand.find(:all, :joins=>[:cars], :conditions=>["brandname LIKE '%ford%'"])
Its because i already have a function that returns all conditions on a single string, but i require to support search in strings and i don't really how to get it work.
Any help will be appreciated.

I'm not entirely certain that I understand what you're talking about. Are you trying to pass in a variable into the conditions?
I would re-write this query just a tad.
Brand.all.joins(:cars).where("brandname LIKE ?", "%#{some_variable}%")
Of course selecting all can be bad for performance if you get a lot of records so you may want to consider limiting that or paginating the results somehow.
I would recommend the guides. Using an array would be great in this instance
Brand.all.joins(:cars).where("brandname LIKE ?", "%#{params[:brand_search]}%")

Related

What is a efficient way to query for this information? [RoR]

Okay basically I'm trying to query the community_posts model and count the amount of posts where .community_topic_id is equal to community_topic which is a param. I was looking over the doc and I have a few ideas of how to do but, I want to make sure I'm doing it right as I have a few similar queries I'm writing for various other methods.
Hope this isn't too broad.. Not trying to ignite a "opinion war" I just want a way to do that wont turn out to be inefficient and force me to change my other queries.
Appreciate your help.
def topicreplycount(community_topic)
"Code for query"
end
CommunityPost.count(community_topic_id: community_topic)

Rails: How to simplify ".select(:my_field).map(&:my_field)"?

To get the invoice numbers of selected jobs I do:
Job.where(...).map(&:invoice_number)
Since the invoice numbers is all I need, I thought to add select(:invoice_number) (I assume the SQL query becomes more efficient this way):
Job.where(...).select(:invoice_number).map(&:invoice_number)
Is there a better way to do the same ? (the .select(:invoice_number).map(&:invoice_number) part seems inefficient to me)
You could always use select_values. Something akin to:
Job.connection.select_values(Job.where(...).select(:invoice_number).to_sql)
This avoids the instantiation of ActiveRecord objects.
I know that this question is rather old, but in case anybody else checks this out, this can be achieved with pluck (http://apidock.com/rails/ActiveRecord/Calculations/pluck). As per http://edgeguides.rubyonrails.org/active_record_querying.html#pluck "pluck makes it possible to replace code like: Client.select(:id).map(&:id) with Client.pluck(:id)"
Would love to be proven wrong, but.. I don't think it's possible
Since all the active record methods are chainable, a method that returned an array of strings would break this. If such a method existed then it wouldn't be in AR, I can't think of where else to look..
You can use GROUP_CONCAT.
invoice_numbers = Job.where(...).select('group_concat(invoice_number) as invoice_numbers').
first.invoice_numbers.split(',').map(&:to_i)
This approach is too long and is not very obvious, but it will run faster than
Job.where(...).select(:invoice_number).map(&:invoice_number)

Complex search screens in Rails 3

I need to implement some search functionality within a Rails application. Most of the stuff I have found is generally aimed at simple plain-text search. I am trying to implement something much more specific. The sort of functionality I am looking to create is this (from a C application):
http://andyc.ac/query.gif
The form just submits the data entered by the user. So I need to translate strings like "3..7" into SQL conditions for the where method e.g.
TestLine.where( "test_int >= ? and test_int <= ?", MinInt, MaxInt )
It seems like this is something that already exists somewhere. The exact format expected is not too important, as the users are not shared between the Rails and C applications. How would this be done?
FWIW the specific functionality you describe is actually supported directly. Well.. almost. From the docs:
A range may be used in the hash to use the SQL BETWEEN operator:
Student.where(:grade => 9..12)
Of course then it's a matter of translating the user's string input to a Range, which isn't very complex, e.g.:
def str_to_range str
str =~ /(\d+)\.\.(\d+)/
Range.new *$~.captures.map(&:to_i)
end
It would probably make the most sense in a scope on your model. (Of course a shortcut would be to simply eval '9..12' but evaling input from the end user is a really, really bad idea.)
Give a look at thinking sphinx(http://freelancing-god.github.com/ts/en/). It might make your task a lot easier. You can search in that:
http://freelancing-god.github.com/ts/en/searching.html#basic

Do "like" queries with ActiveRecord in Rails 2.x and 3.x?

I'm doing queries like this in Rails 3.x
Speaker.where("name like '%yson%'")
but I'd love to avoid the DB specific code. What's the right way to do this?
If there's a way to do this in Rails 2.x too, that would help too.
In Rails 3 or greater
Speaker.where("name LIKE ?", "%yson%")
In Rails 2
Speaker.all(:conditions => ["name LIKE ?", "%yson%"])
Avoid to directly interpolate strings because the value won't be escaped and you are vulnerable to SQL injection attacks.
You can use .matches for it.
> t[:name].matches('%lore').to_sql
=> "\"products\".\"name\" LIKE '%lore'"
Actual usage in a query would be:
Speaker.where(Speaker.arel_table[:name].matches('%lore'))
Use a search engine like solr or sphinx to create indexes for the columns you would be performing like queries on. Like queries always result in a full table scan when you look at the explain plan so you really should almost never use them in a production site.
Not by default in Rails, since there are so many DB options (MySQL, Postgresql, MongoDB, CouchDB...), but you can check out gems like MetaWhere, where you can do things like:
Article.where(:title.matches => 'Hello%', :created_at.gt => 3.days.ago)
=> SELECT "articles".* FROM "articles" WHERE ("articles"."title" LIKE 'Hello%')
AND ("articles"."created_at" > '2010-04-12 18:39:32.592087')
In general though you'll probably have to have some DB specific code, or refactor your code (i.e redefine the .matches operator on symbols in MetaWhere) to work with a different database. Hopefully you won't be changing your database that often, but if you are you should have a centralized location where you define these operators for re-use. Keep in mind that an operator or function defined in one database might not be available in another, in which case having this generalized operation is moot since you won't be able to perform the search anyways.

Sanitizing data at active record

I want to sanitize the data coming from my form in ActiveRecord. Especially the apostrophe before its actually included into the SQL query. I want it to be something raghu'\s if raghu's is been inputed. I have already tried using:
sanitize_sql_array
sanitize_sql_for_assignment
sanitize_sql_for_conditions
sanitize_sql_hash_for_assignment
sanitize_sql_hash_for_conditions
But none of these seem to escape the apostrophe there by failing my SQL query.
Rails will handle a lot of the santizing for you if you use the following format for performing finds. It'll run the necessary sub methods to ensure that nothing potentially destructive is inserted into the database. Not sure about the single inverted comma, but it's worth a shot.
Model.find(:all, :condition => ["text_value = ?", params[:form_input])
You might want to have a look at this thread - Strip & Sanitize BEFORE saving data from the Ruby Forum - I haven't tried any of the solutions mentioned but it might get you going in the right direction

Resources