I'm attempting to return records from two database tables (pages and articles) that match each of the words in a search term. Here's my query:
if params.has_key?('search_term')
words = params['search_term'].split(' ')
query = "
select
p.id
, p.title
, p.slug
, p.created_at
, p.content
, 'page' as type
from pages p
where 1 = 1
"
words.each do |word|
query << " and p.title like '%" << word << "%' or p.content like '%" << word << "%'"
end
query << "
union all
select
a.id
, a.title
, a.slug
, a.created_at
, a.content
, 'article' as type
from articles a
where 1 = 1
"
words.each do |word|
query << " and a.title like '%" << word << "%' or a.content like '%" << word << "%'"
end
@search_results = ActiveRecord::Base.connection.execute(query)
end
Firstly, how can I sanitise the value of word
inside the loops to prevent a SQL injection attack? I'm wondering if it's necessary to sanitise word
further because I've already split the search term string.
Secondly, would there be a better way to approach what I'm trying to do? I'm relatively new to Ruby/Rails so would welcome any pointers.
Thanks in advance for your help.
You should the built in querying tools as much as possible. So assuming you have a Page class and and Article class you can use select and where
matched_pages = Page.select(:title, :slug, :created_at, :content)
matched_articles = Articles.select(:title, :slug, :created_at, :content)
words.each do |word|
matched_pages = matched_pages.where(["title LIKE :word OR content LIKE :word", {word: "%#{word}%"}])
matched_articles = matched_articles.where(["title LIKE :word OR content LIKE :word", {word: "%#{word}%"}])
end
If you need them merged together you could concatenate the two results something like
@search_results = matched_pages + matched_articles
Then if you want it in a view:
<% @search_results.each do |item| %>
<tr>
<td><%= item.title %></td>
<td><%= item.slug %></td>
<td><%= item.created_at %></td>
<td><%= item.content %></td>
<td><%= item.class.name.downcase %></td>
</tr>
<% end %>
Of course there are many other things you may want to do with it and there are other (usually better) ways to display the data in a view than the example, but that should help you get some idea what the data would look like.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.