2014-12-29 3 views
1

Я пытаюсь вернуть записи из двух таблиц базы данных (страницы и статьи), которые соответствуют каждому из слов в поисковом выражении. Вот мой запрос:Rails 4 возвращает записи из нескольких таблиц, соответствующих поисковому запросу

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 

Во-первых, как я могу дезинфицировать значение word внутри петли, чтобы предотвратить инъекции SQL атаки? Мне интересно, нужно ли еще дезинфицировать word, потому что я уже разделил строку слова поиска.

Во-вторых, будет ли лучший способ приблизиться к тому, что я пытаюсь сделать? Я относительно новичок в Ruby/Rails, поэтому приветствовал бы любые указатели.

Заранее за вашу помощь.

ответ

1

Вы должны использовать встроенные инструменты запросов как можно больше. Таким образом, если у вас есть класс страницы и и статьи класса можно использовать select и 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 

Если вы нуждаетесь в них объединены вместе, вы могли бы объединить два результата что-то вроде

@search_results = matched_pages + matched_articles 

Тогда, если вы хотите в целях:

<% @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 %> 

конечно, есть много других вещей, которые вы можете сделать с этим существуют и другие (как правило, лучше) способы кадрир заложите данные в представлении, чем пример, но это должно помочь вам понять, как будут выглядеть данные.

+0

Это работает хорошо. Спасибо за вашу помощь. –

Смежные вопросы